<?php
class Sales_Order extends QDB_ActiveRecord_Abstract
{
	/**
	 * 返回对象的定义
	 *
	 * @static
	 *
	 * @return array
	 */
	static function __define()
	{
		return array
		(
			// 指定该 ActiveRecord 要使用的行为插件
			'behaviors' => '',

			// 指定行为插件的配置
			'behaviors_settings' => array
			(
				# '插件名' => array('选项' => 设置),
			),

			// 用什么数据表保存对象
			'table_name' => 'sales_order',

			// 指定数据表记录字段与对象属性之间的映射关系
			// 没有在此处指定的属性，QeePHP 会自动设置将属性映射为对象的可读写属性
			'props' => array
			(
				// 主键应该是只读，确保领域对象的“不变量”
				'id' => array('readonly' => true),

				/**
				 *  可以在此添加其他属性的设置
				 */
				# 'other_prop' => array('readonly' => true),

				/**
				 * 添加对象间的关联
				 */
				# 'other' => array('has_one' => 'Class'),

			),

			/**
			 * 允许使用 mass-assignment 方式赋值的属性
			 *
			 * 如果指定了 attr_accessible，则忽略 attr_protected 的设置。
			 */
			'attr_accessible' => '',

			/**
			 * 拒绝使用 mass-assignment 方式赋值的属性
			 */
			'attr_protected' => 'id',

			/**
			 * 指定在数据库中创建对象时，哪些属性的值不允许由外部提供
			 *
			 * 这里指定的属性会在创建记录时被过滤掉，从而让数据库自行填充值。
			 */
			'create_reject' => '',

			/**
			 * 指定更新数据库中的对象时，哪些属性的值不允许由外部提供
			 */
			'update_reject' => '',

			/**
			 * 指定在数据库中创建对象时，哪些属性的值由下面指定的内容进行覆盖
			 *
			 * 如果填充值为 self::AUTOFILL_TIMESTAMP 或 self::AUTOFILL_DATETIME，
			 * 则会根据属性的类型来自动填充当前时间（整数或字符串）。
			 *
			 * 如果填充值为一个数组，则假定为 callback 方法。
			 */
			'create_autofill' => array
			(
				# 属性名 => 填充值
				# 'is_locked' => 0,
			),

			/**
			 * 指定更新数据库中的对象时，哪些属性的值由下面指定的内容进行覆盖
			 *
			 * 填充值的指定规则同 create_autofill
			 */
			'update_autofill' => array
			(
			),

			/**
			 * 在保存对象时，会按照下面指定的验证规则进行验证。验证失败会抛出异常。
			 *
			 * 除了在保存时自动验证，还可以通过对象的 ::meta()->validate() 方法对数组数据进行验证。
			 *
			 * 如果需要添加一个自定义验证，应该写成
			 *
			 * 'title' => array(
			 *	array(array(__CLASS__, 'checkTitle'), '标题不能为空'),
			 * )
			 *
			 * 然后在该类中添加 checkTitle() 方法。函数原型如下：
			 *
			 * static function checkTitle($title)
			 *
			 * 该方法返回 true 表示通过验证。
			 */
			'validations' => array
			(
			),
		);
	}


/* ------------------ 以下是自动生成的代码，不能修改 ------------------ */

	/**
	 * 开启一个查询，查找符合条件的对象或对象集合
	 *
	 * @static
	 *
	 * @return QDB_Select
	 */
	static function find()
	{
		$args = func_get_args();
		return QDB_ActiveRecord_Meta::instance(__CLASS__)->findByArgs($args);
	}

	/**
	 * 返回当前 ActiveRecord 类的元数据对象
	 *
	 * @static
	 *
	 * @return QDB_ActiveRecord_Meta
	 */
	static function meta()
	{
		return QDB_ActiveRecord_Meta::instance(__CLASS__);
	}


/* ------------------ 以上是自动生成的代码，不能修改 ------------------ */
	/**
	 * 创建销售订单
	 * @param $order 销售订单信息
	 */
	static function create($order)
	{
		$generate_result = Number_Rules::generate('sales_order', 'S');
		if ($generate_result['ack'] == SUCCESS)
		{
			$sales_order = new Sales_Order();
			$sales_order->number = $generate_result['number'];
			$sales_order->warehouse_id = $order['warehouse_id'];
			$sales_order->shop_id = $order['shop_id'];
			$sales_order->shop_order_number = empty($order['shop_order_number']) ? 0 : $order['shop_order_number'];
			if ($order['send_method'] == Q::ini('custom_flag/sales_order_send_method/resend/value'))
			{
				$sales_order->resend_status = Q::ini('custom_flag/sales_order_resend_status/unaudited/value');
				$resend_order = Sales_Order::find('number=?', $order['resend_sales_order_id'])->asArray()->getOne();
				if ($resend_order)
				{
					$sales_order->resend_sales_order_id = $resend_order['id'];
				}
				$sales_order->resend_reason = $order['resend_reason'];
			}
			$sales_order->handle_status = Q::ini('custom_flag/sales_order_handle_status/new/value');
			$sales_order->sales_user_id = $order['sales_user_id'];
			$sales_order->sales_time = $order['sales_time'];
			$sales_order->make_user_id = CURRENT_USER_ID;
			$sales_order->make_time = CURRENT_DATETIME;
			$sales_order->shipping_status = Q::ini('custom_flag/sales_order_shipping_status/pending/value');
			$sales_order->send_method = $order['send_method'];
			$sales_order->shipping_method = $order['shipping_method'];
			$sales_order->payment_status = Q::ini('custom_flag/sales_order_payment_status/paid/value');
			$sales_order->payment_method = $order['payment_method'];
			$sales_order->shipping_fee = $order['shipping_fee'];
			$sales_order->discount = $order['discount'];
			$sales_order->currency_id = $order['currency_id'];
			$currency = Currency::find('id=?', $order['currency_id'])->asArray()->getOne();
			$sales_order->currency_rate = $currency['rate'];
			$sales_order->transaction_id = $order['transaction_id'];
			$sales_order->save();
			$sales_order_id = mysql_insert_id();
			//customer info
			$customer = new Sales_Order_Customer_Info();
			$customer->sales_order_id = $sales_order_id;
			$customer->shop_buyer_id = $order['shop_buyer_id'];
			$customer->fullname = $order['fullname'];
			$customer->phone = $order['phone'];
			$customer->email = $order['email'];
			$customer->street1 = $order['street1'];
			$customer->street2 = $order['street2'];
			$customer->city = $order['city'];
			$customer->state = $order['state'];
			$customer->zip = $order['zip'];
			$customer->country = $order['country'];
			$customer->country_cn = $order['country_cn'];
			$customer->address_notes = $order['address_notes'];
			$customer->save();
			$item_result = Sales_Order_Item::update($order['item'], $sales_order_id, 'all_as_new');
			$sales_order = Sales_Order::updateOrder($sales_order_id);
			$sales_order = Sales_Order::updateEstimatedWeight($sales_order_id);
			if ($item_result['ack'] == SUCCESS)
			{
				return array('ack' => SUCCESS, 'message' => '', 'sales_order_id' => $sales_order_id);
			}
			else
			{
				return array('ack' => $item_result['ack'], 'message' => $item_result['message'], 'sales_order_id' => $sales_order_id);
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'cannot create number');
		}
	}
	
	/**
	 * 批量导入订单
	 * @param $orders 订单数组
	 */
	static function import($orders)
	{
		$default_warehouse_id = Warehouse::getDefaultWarehouseId();
		$message = array();
		foreach ($orders as $o)
		{
			$judge_result = Sales_Order::judgeImport($o['shop_id'], $o['shop_order_number'], $o['item']);
			if ($judge_result['ack'] == SUCCESS)
			{
				if ($judge_result['type'] == 'create')
				{
					$order_id = 0;
					$old_warehouse = 0;
					$generate_result = Number_Rules::generate('sales_order', 'S');
					$order_number = $generate_result['number'];
					$sales_order = new Sales_Order();
					$sales_order->number = $generate_result['number'];
					$sales_order->shop_id = $o['shop_id'];
					$sales_order->shop_order_number = $o['shop_order_number'];
					$sales_order->make_user_id = CURRENT_USER_ID;
					$sales_order->make_time = CURRENT_DATETIME;
				}
				elseif ($judge_result['type'] == 'replace')
				{
					$sales_order = Sales_Order::find('shop_id=? and shop_order_number=?', $o['shop_id'], $o['shop_order_number'])->getOne();
					$order_id = $sales_order['id'];
					$old_warehouse = $sales_order['warehouse_id'];
					$order_number = $sales_order['number'];
				}
				$sales_order->warehouse_id = $default_warehouse_id;
				$sales_order->sales_user_id = CURRENT_USER_ID;
				$sales_order->sales_time = $o['sales_time'];
				$sales_order->paid_time = $o['paid_time'];
				$sales_order->shipping_status = Q::ini('custom_flag/sales_order_shipping_status/pending/value');
				$sales_order->send_method = Q::ini('custom_flag/sales_order_send_method/normal/value');
				$sales_order->shipping_method = $o['shipping_method'];
				$sales_order->payment_method = $o['payment_method'];
				$sales_order->shipping_fee = $o['shipping_fee'];
				$sales_order->discount = $o['discount'];
				$sales_order->amount = $o['amount'];
				$sales_order->currency_id = $o['currency_id'];
				$sales_order->currency_rate = $o['currency_rate'];
				$sales_order->transaction_id = $o['transaction_id'];
				$sales_order->save();
				if ( ! $order_id)
				{
					$order_id = mysql_insert_id();
				}
				$customer = Sales_Order_Customer_Info::find('sales_order_id=?', $order_id)->getOne();
				if ( ! $customer['id'])
				{
					$customer = new Sales_Order_Customer_Info();
					$customer->sales_order_id = $order_id;
				}
				$customer->shop_buyer_id = isset($o['shop_buyer_id']) ? $o['shop_buyer_id'] : '';
				$customer->fullname = $o['fullname'];
				$customer->phone = $o['phone'];
				$customer->email = $o['email'];
				$customer->street1 = $o['street1'];
				$customer->street2 = $o['street2'];
				$customer->city = $o['city'];
				$customer->state = $o['state'];
				$customer->zip = $o['zip'];
				$customer->country = $o['country'];
				$customer->country_cn = $o['country_cn'];
				$customer->save();
				if (isset($o['buyer_message']) && $o['buyer_message'])
				{
					$notes = Sales_Order_Notes::find('sales_order_id=? and type=?', $order_id, Q::ini('custom_flag/sales_order_notes_type/customer/value'))->getOne();
					if ( ! $notes['id'])
					{
						$notes = new Sales_Order_Notes();
						$notes->sales_order_id = $order_id;
						$notes->type = Q::ini('custom_flag/sales_order_notes_type/customer/value');
					}
					$notes->notes = $o['buyer_message'];
					$notes->save();
				}
				$item_result = Sales_Order_Item::update($o['item'], $order_id, 'all_as_new', $old_warehouse);
				if ($item_result['ack'] != SUCCESS)
				{
					$message[] = $order_number . ':' .$item_result['message'];
				}
				$param = isset($o['param']) ? $o['param'] : array();
				Sales_Order::updateOrder($order_id);
				Sales_Order::selectShippingMethod($order_id, $param);
				Sales_Order::updateEstimatedWeight($order_id);
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断单个订单是否可以导入
	 * @param $shop_id 网点id
	 * @param $shop_order_number 网点订单号
	 */
	static function judgeImport($shop_id, $shop_order_number, $item = array())
	{
		$sales_order = Sales_Order::find('shop_id=? and shop_order_number=?', $shop_id, $shop_order_number)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['edit_flag'] == Q::ini('custom_flag/sales_order_edit_flag/new/value') && $sales_order['send_method'] == Q::ini('custom_flag/sales_order_send_method/normal/value') && $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value'))
			{
				return array('ack' => SUCCESS, 'message' => '', 'type' => 'replace');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order is already edited');
			}
		}
		else
		{
			$shop = Shop::find('id=?', $shop_id)->asArray()->getOne();
			if ($shop['platform'] == 'ebay')
			{
				if (isset($item[0]['shop_item_id']))
				{
					$sales_order_item = Sales_Order_Item::find('shop_item_id=? and shop_transaction_id=?', $item[0]['shop_item_id'], $item[0]['shop_transaction_id'])->asArray()->getOne();
					if ($sales_order_item)
					{
						return array('ack' => FAILURE, 'message' => 'sales order is repeat', 'type' => '');
					}
				}
			}
			return array('ack' => SUCCESS, 'message' => '', 'type' => 'create');
		}
	}
	
	/**
	 * 编辑订单信息
	 * @param $order 订单信息
	 */
	static function editOrderInfo($order)
	{
		$judge_result = Sales_Order::judgeEditOrderInfo($order['id']);
		if ($judge_result['ack'] == SUCCESS)
		{
			$sales_order = Sales_Order::find('id=?', $order['id'])->getOne();
			if ($sales_order['shipping_method'] !== $order['shipping_method'])
			{
				$sales_order->lsp_number = '';
				$sales_order->tracking_number = '';
				$sales_order->synchronous_flag = '';
			}
			$currency_rate = QDB::getConn()->execute('select rate from currency where id=' . $order['currency_id'])->fetchOne();
			$sales_order->payment_method = $order['payment_method'];
			$sales_order->transaction_id = $order['transaction_id'];
			$sales_order->send_method = $order['send_method'];
			$sales_order->sales_time = $order['sales_time'];
			$sales_order->currency_id = $order['currency_id'];
			$sales_order->currency_rate = $currency_rate;
			if ($order['send_method'] == Q::ini('custom_flag/sales_order_send_method/resend/value'))
			{
				$resend_order = Sales_Order::find('number=?', $order['resend_sales_order_id'])->asArray()->getOne();
				$sales_order->resend_reason = $order['resend_reason'];
				$sales_order->resend_sales_order_id = $resend_order ? $resend_order['id'] : 0;
			}
			else
			{
				$sales_order->resend_reason = 0;
				$sales_order->resend_sales_order_id = 0;
			}
			$sales_order->shipping_method = $order['shipping_method'];
			$sales_order->shipping_fee = $order['shipping_fee'];
			$sales_order->discount = $order['discount'];
			$sales_order->edit_flag = Q::ini('custom_flag/sales_order_edit_flag/edited/value');
			$sales_order->save();
			$customer_info = Sales_Order_Customer_Info::find('sales_order_id=?', $order['id'])->getOne();
			$customer_info->shop_buyer_id = $order['shop_buyer_id'];
			$customer_info->fullname = $order['fullname'];
			$customer_info->phone = $order['phone'];
			$customer_info->email = $order['email'];
			$customer_info->street1 = $order['street1'];
			$customer_info->street2 = $order['street2'];
			$customer_info->city = $order['city'];
			$customer_info->state = $order['state'];
			$customer_info->zip = $order['zip'];
			$customer_info->country = $order['country'];
			$customer_info->country_cn = $order['country_cn'];
			$customer_info->address_notes = $order['address_notes'];
			$customer_info->save();
			Sales_Order::updateOrder($order['id']);
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $judge_result['message']);
		}
	}
	
	/**
	 * 判断订单是否可以编辑订单信息
	 * @param $sales_order_id 订单id
	 */
	static function judgeEditOrderInfo($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order handle status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 编辑订单产品信息
	 * @param $order 订单数据
	 */
	static function editProductInfo($order)
	{
		$judge_result = Sales_Order::judgeEditProductInfo($order);
		if ($judge_result['ack'] == SUCCESS)
		{
			$sales_order = Sales_Order::find('id=?', $order['id'])->getOne();
			$old_warehouse_id = $sales_order['warehouse_id'];
			$sales_order->warehouse_id = $order['warehouse_id'];
			$sales_order->shipping_method = $order['shipping_method'];
			$sales_order->edit_flag = Q::ini('custom_flag/sales_order_edit_flag/edited/value');
			$sales_order->save();
			$item_result = Sales_Order_Item::update($order['item'], $order['id'], 'check_db', $old_warehouse_id);
			Sales_Order::updateOrder($order['id']);
			Sales_Order::updateEstimatedWeight($order['id']);
			if ($item_result['ack'] == SUCCESS)
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => $item_result['ack'], 'message' => $item_result['message']);
			}
		}
		else
		{
			return array('ack' => $judge_result['ack'], 'message' => $judge_result['message']);
		}
	}
	
	/**
	 * 判断是否可以编辑订单产品信息
	 * @param $order 订单信息
	 */
	static function judgeEditProductInfo($order)
	{
		$not_exists_product_warehouse = array();
		$sales_order = Sales_Order::find('id=?', $order['id'])->asArray()->getOne();
		$old_warehouse_id = $sales_order['warehouse_id'];
		if ($sales_order)
		{
			if ($sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/normal/value'))
			{
				if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value'))
				{
					foreach ($order['item'] as $oi)
					{
						$product = Product_Warehouse::find('product_basic.number=? and product_warehouse.warehouse_id=?', $oi['product_basic_number'], $order['warehouse_id'])
							->joinLeft('product_basic', '', 'product_basic.id=product_warehouse.product_basic_id')
							->asArray()->getOne();
						if (empty($product['id']))
						{
							$not_exists_product_warehouse[] = $oi['product_basic_number'];
						}
					}
					if ($not_exists_product_warehouse)
					{
						return array('ack' => PARTIAL_FAILURE, 'message' => implode(',', $not_exists_product_warehouse) . ' not exists product warehouse');
					}
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => 'sales order handle status is incorrect');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order is already trashed');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 从新单或销售滞留确认订单
	 * @param $sales_order_ids 订单id数组
	 */
	static function changeHandleStatusFromNewOrSalesHoldToCheckout($sales_order_ids)
	{
		$message = array();
		foreach ($sales_order_ids as $key => $id)
		{
			$judge_result = Sales_Order::judgeChangeHandleStatusFromNewOrSalesHoldToCheckout($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				QDB::getConn()->execute('update sales_order set handle_status=' . Q::ini('custom_flag/sales_order_handle_status/checkout/value') . ',checkout_user_id=' . CURRENT_USER_ID . ',checkout_time=\'' . CURRENT_DATETIME . '\',edit_flag=' . Q::ini('custom_flag/sales_order_edit_flag/edited/value') . ',tips_flag=0 where id=' . $id);
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断销售单是否可以从新单或销售滞留转变为确认
	 * @param $sales_order_id
	 */
	static function judgeChangeHandleStatusFromNewOrSalesHoldToCheckout($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/normal/value'))
			{
				if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value'))
				{
					if (($sales_order['shipping_method'] == Shipping_Method::getShippingMethodByCode('GZ_N_EUB') || $sales_order['shipping_method'] == Shipping_Method::getShippingMethodByCode('GZ_N_IEUB')) && (! is_file(Q::ini('custom_system/eub_label_dir') . $sales_order['number'] . '.pdf') || ! $sales_order['tracking_number']))
					{
						return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': EUB not Sync');
					}
					else
					{
						return array('ack' => SUCCESS, 'message' => '');
					}
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order handle status is incorrect');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order is already trashed');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 销售订单从新单或销售确认变为销售滞留
	 * @param $sales_order_ids
	 */
	static function changeHandleStatusFromNewOrCheckoutToSalesHold($sales_order_ids)
	{
		$message = array();
		foreach ($sales_order_ids as $key => $id)
		{
			$judge_result = Sales_Order::judgeChangeHandleStatusFromNewOrCheckoutToSalesHold($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				QDB::getConn()->execute('update sales_order set handle_status=' . Q::ini('custom_flag/sales_order_handle_status/sales_hold/value') . ',edit_flag=' . Q::ini('custom_flag/sales_order_edit_flag/edited/value') . ' where id=' . $id);
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断销售订单从新单或销售确认变为销售滞留
	 * @param $sales_order_id
	 */
	static function judgeChangeHandleStatusFromNewOrCheckoutToSalesHold($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/normal/value'))
			{
				if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/checkout/value'))
				{
					return array('ack' => SUCCESS, 'message' => '', 'handle_status' => $sales_order['handle_status']);
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $sales_order['number'] . '订单状态错误');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . '订单已废弃');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '订单不存在！');
		}
	}
	
	/**
	 * 保存重量和根据公式计算运费
	 * @param $sales_order_id
	 * @param $weight
	 */
	static function changeHandleStatusFromPrintedToWeighed($sales_order_id, $weight)
	{
		$judge_result = Sales_Order::judgeChangeHandleStatusFromPrintedToWeighed($sales_order_id);
		if ($judge_result['ack'] == SUCCESS)
		{
			$sales_order = Sales_Order::find('id=?', $sales_order_id)->getOne();
			$formula = Shipping_Method::find('id=?', $sales_order['shipping_method'])->asArray()->getOne();
			if ($formula)
			{
				$w = $weight;
				eval('$postage=' . $formula['formula']);
			}
			else
			{
				$postage = 0;
			}
			$sales_order->weigh_user_id = CURRENT_USER_ID;
			$sales_order->weigh_time = CURRENT_DATETIME;
			$sales_order->weight = $weight;
			$sales_order->postage = $postage;
			return array('ack' => SUCCESS, 'message' => '', 'postage' => $postage);
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $judge_result['message']);
		}
	}
	
	/**
	 * 判断订单是否可以称重
	 * @param $sales_order_id
	 */
	static function judgeChangeHandleStatusFromPrintedToWeighed($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asas->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/printed_address/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order handle status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 销售订单从已打印或已称重变为仓库滞留（多个）
	 * @param $sales_order_ids
	 */
	static function changeHandleStatusToStorageHold($sales_order_ids)
	{
		$message = array();
		foreach ($sales_order_ids as $id)
		{
			$judge_result = Sales_Order::judgeChangeHandleStatusToStorageHold($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				Sales_Order_Item::availableQuantityIncrease($id);
				QDB::getConn()->execute('update sales_order set handle_status=' . Q::ini('custom_flag/sales_order_handle_status/warehouse_hold/value') . ' where id=' .$id);
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断销售订单从已打印或已称重变为仓库滞留
	 * @param unknown_type $sales_order_id
	 */
	static function judgeChangeHandleStatusToStorageHold($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/printed/value')
				|| $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/printed_address/value')
				|| $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/weighed/value')
				|| $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/assigned/value'))
			{
				if ($sales_order['synchronous_flag'] == Q::ini('custom_flag/sales_order_synchronous_flag/Winit/value') && $sales_order['lsp_number'])
				{
					$result = Helper_BSS_API::winitAPICall(Helper_BSS_API::winitSign(array('outboundOrderNum' => $sales_order['lsp_number']), 'queryOutboundOrder'), Q::ini('custom_api/Winit_api_uri'));
					if ($result['ack'] == FAILURE)
					{
						return array('ack' => FAILURE, 'message' => $result['message']);
					}
					else
					{
						$dataList = $result['data']['list'];
						foreach ($dataList as $k => $data)
						{
							if (in_array($data['status'], array('VOI', 'VO')))
							{
								$update_sales_order = QDB::getConn()->execute('update sales_order set lsp_number=NULL, synchronous_flag=NULL where lsp_number=\'' . $sales_order['lsp_number'] . '\'');
								if ($update_sales_order)
								{
									return array('ack' => SUCCESS, 'message' => '');
								}
								else
								{
									return array('ack' => FAILURE, 'message' => '清除同步数据失败！');
								}
							}
							else
							{
								$update_winit_result = Sales_Order::updateWinitStatusToVoid($sales_order['lsp_number']);
								return array('ack' => $update_winit_result['ack'], 'message' => $update_winit_result['message']);
							}
						}
					}
				}
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order handle status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 销售订单从仓库滞留转变为销售滞留
	 * @param $sales_order_ids 销售订单id
	 * @param $note_content 添加的备注内容
	 * @param $type 备注的类型
	 */
	static function changeHandleStatusFromStorageHoldToSalesHold($sales_order_ids, $note_content)
	{
		$message = array();
		foreach ($sales_order_ids as $key => $id)
		{
			$judge_result = Sales_Order::judgeChangeHandleStatusFromStorageHoldToSalesHold($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				QDB::getConn()->execute('update sales_order set handle_status=' . Q::ini('custom_flag/sales_order_handle_status/sales_hold/value') . ' where id=' . $id);
				Sales_Order_Notes::create($id, $note_content, Q::ini('custom_flag/sales_order_notes_type/warehouse/value'));
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断销售订单是否可以从仓库滞留转变为销售滞留
	 * @param $sales_order_id
	 */
	static function judgeChangeHandleStatusFromStorageHoldToSalesHold($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/warehouse_hold/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order handle status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order is not exists');
		}
	}
	
	/**
	 * 销售订单从仓库滞留转变为销售确认
	 * @param $sales_order_ids
	 */
	static function changeHandleStatusFromStorageHoldToCheckout($sales_order_ids)
	{
		$message = array();
		foreach ($sales_order_ids as $id)
		{
			$judge_result = Sales_Order::judgeChangeHandleStatusFromStorageHoldToCheckout($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				QDB::getConn()->execute('update sales_order set handle_status=' . Q::ini('custom_flag/sales_order_handle_status/checkout/value') . ' where id=' . $id);
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断销售订单是否可以从仓库滞留转变为销售确认
	 * @param $sales_order_id
	 */
	static function judgeChangeHandleStatusFromStorageHoldToCheckout($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/warehouse_hold/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order handle status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 销售订单从销售确认转变为已配货
	 * @param $sales_order_ids
	 */
	static function changeHandleStatusFromCheckoutToAssigned($sales_order_ids)
	{
		$message = array();
		foreach ($sales_order_ids as $id)
		{
			$judge_result = Sales_Order::judgeChangeHandleStatusFromCheckoutToAssigned($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				Sales_Order_Item::availableQuantityDecrease($id);
				Sales_Order::updateSortShelfPosition($id);
				QDB::getConn()->execute('update sales_order set handle_status=' . Q::ini('custom_flag/sales_order_handle_status/assigned/value') . ' where id=' . $id);
				Sales_Order::updateEstimatedWeight($id);
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断销售订单是否可以从销售确认变为已配货
	 * @param $sales_order_id
	 */
	static function judgeChangeHandleStatusFromCheckoutToAssigned($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/normal/value'))
			{
				if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/checkout/value'))
				{
					$item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
					$product = array();
					$enough = true;
					foreach ($item as $i)
					{
						$key = $i['product_basic_id'] . '_' . $sales_order['warehouse_id'];
						if ( ! array_key_exists($key, $product))
						{
							$product_warehouse = Product_Warehouse::find('product_basic_id=? and warehouse_id=?', $i['product_basic_id'], $sales_order['warehouse_id'])
								->joinLeft('warehouse', 'name as warehouse_name', 'warehouse.id=product_warehouse.warehouse_id')
								->joinLeft('product_basic', 'number', 'product_basic.id=product_warehouse.product_basic_id')
								->asArray()->getOne();
							$product[$key] = array(
								'product_number' => $product_warehouse['number'],
								'warehouse_name' => $product_warehouse['warehouse_name'],
								'available_quantity' => $product_warehouse['available_quantity'],
								'need_quantity' => 0
							);
						}
						$product[$key]['need_quantity'] += $i['quantity'];
						if ($product[$key]['available_quantity'] < $product[$key]['need_quantity'])
						{
							$enough = false;
						}
					}
					if ($enough)
					{
						return array('ack' => SUCCESS, 'message' => '');
					}
					else
					{
						return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': available quantity is not enough');
					}
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order handle status is incorrect');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order is already trashed');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 标识错/漏发订单信息
	 * @param $sales_order_ids 销售订单id
	 * @param $mark_order_flag 错/漏发订单原因
	 */
	static function markOrder($sales_order_id, $mark_order_flag)
	{
		$judge_result = Sales_Order::judgeMarkOrder($sales_order_id);
		if ($judge_result['ack'] == SUCCESS)
		{
			QDB::getConn()->execute('update sales_order set mark_order_flag ='. $mark_order_flag . ' where id=' . $sales_order_id);
		}
		return $judge_result;
	}
	
	/**
	 * 判断订单是否满足标识漏/错发条件
	 * @param $sales_order_id
	 */
	static function judgeMarkOrder($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/shipped/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . '：该订单尚未发货！');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '订单不存在！');
		}
	}
	
	/**
	 * 废弃订单
	 * @param $sales_order_ids
	 * @param $trash_reason
	 */
	static function trash($sales_order_ids, $trash_reason)
	{
		$message = array();
		foreach ($sales_order_ids as $key => $id)
		{
			$judge_result = Sales_Order::judgeTrash($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				Sales_Order_Item::soldQauntityDecrease($id);
				QDB::getConn()->execute('update sales_order set trash_status=' . Q::ini('custom_flag/sales_order_trash_status/trashed/value') . ',trash_reason=\'' . $trash_reason . '\',trash_user_id=' . CURRENT_USER_ID . ',trash_time=\'' . CURRENT_DATETIME . '\',edit_flag=' . Q::ini('custom_flag/sales_order_edit_flag/edited/value') . ' where id=' . $id);
			}
			else
			{
				$message[] = 'No.' . ($key + 1) . ' ' . $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断订单是否满足废弃条件
	 * @param $sales_order_id
	 */
	static function judgeTrash($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/trashed/value'))
			{
				return array('ack' => FAILURE, 'message' => 'sales order has already trashed');
			}
			else
			{
				if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value'))
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => 'sales order handle status is incorrect');
				}
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 废弃单恢复
	 * @param $sales_order_id
	 */
	static function trashReturn($sales_order_id)
	{
		$judge_result = Sales_Order::judgeTrashReturn($sales_order_id);
		if ($judge_result['ack'] == SUCCESS)
		{
			Sales_Order_Item::soldQuantityIncrease($sales_order_id);
			QDB::getConn()->execute('update sales_order set trash_status=' . Q::ini('custom_flag/sales_order_trash_status/normal/value') . ',edit_flag=' . Q::ini('custom_flag/sales_order_edit_flag/edited/value') . ' where id=' . $sales_order_id);
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $judge_result['message']);
		}
	}
	
	/**
	 * 判断订单是否满足废弃恢复条件
	 * @param $sales_order_id
	 */
	static function judgeTrashReturn($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/trashed/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order is not trashed');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 删除销售单
	 * @param $sales_order_ids
	 */
	static function delete($sales_order_ids)
	{
		$message = array();
		foreach ($sales_order_ids as $id)
		{
			$judge_result = Sales_Order::judgeDelete($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				Sales_Order_Notes::delete($id);
				Sales_Order_Item::delete($id);
				Sales_Order::meta()->deleteWhere('id=?', $id);
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断销售订单是否能够删除
	 * @param $sales_order_id 销售单id
	 */
	static function judgeDelete($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/trashed/value'))
			{
				$refund = Sales_Refund::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
				if (count($refund))
				{
					return array('ack' => FAILURE, 'message' => $sales_order['number'] . 'sales order has refund');
				}
				else
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order is not trashed');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 合并销售订单
	 * @param $sales_order_id
	 * @param $number
	 */
	static function combine($sales_order_id, $number)
	{
		$judge_result = Sales_Order::judgeCombine($sales_order_id, $number);
		if ($judge_result['ack'] == SUCCESS)
		{
			foreach ($number as $n)
			{
				$combine_sales_order = Sales_Order::find('number=?', $n)
					->joinLeft('sales_order_customer_info', 'sales_order_customer_info.shop_buyer_id', 'sales_order_customer_info.sales_order_id=sales_order.id')
					->asArray()->getOne();
				$combine_sales_order_arr[$combine_sales_order['id']] = $combine_sales_order;
			}
			QDB::getConn()->execute('update sales_order set edit_flag=' . Q::ini('custom_flag/sales_order_edit_flag/edited/value') . ' where id=' . $sales_order_id);
			$item = array();
			foreach ($combine_sales_order_arr as $co)
			{
				$trash_result = Sales_Order::trash(array($co['id']), '合并单');
				$item = Sales_Order_Item::find('sales_order_item.sales_order_id=?', $co['id'])->asArray()->getAll();
				foreach ($item as $i)
				{
					$i['attr'] = Sales_Order_Item_Attribute::find('sales_order_item_id=?', $i['id'])->asArray()->getAll();
					$item = new Sales_Order_Item();
					$item->sales_order_id = $sales_order_id;
					$item->product_basic_id = $i['product_basic_id'];
					$item->shop_item_id = isset($i['shop_item_id']) ? $i['shop_item_id'] : '';
					$item->shop_transaction_id = isset($i['shop_transaction_id']) ? $i['shop_transaction_id'] : '';
					$item->quantity = $i['quantity'];
					$item->sales_price = $i['sales_price'];
					$item->gift_flag = (isset($i['gift_flag']) && $i['gift_flag'] == Q::ini('custom_flag/sales_order_item_gift_flag/gift/value')) ? Q::ini('custom_flag/sales_order_item_gift_flag/gift/value') : Q::ini('custom_flag/sales_order_item_gift_flag/not/value');
					$item->save();
					$sales_order_item_id = mysql_insert_id();
					if (isset($i['attr']))
					{
						Sales_Order_Item_Attribute::update($i['attr'], $sales_order_item_id);
					}
				}
				Sales_Order_Item::soldQuantityIncrease($co['id']);
				$sales_order_combine_mapping = new Sales_Order_Combine_Mapping();
				$sales_order_combine_mapping->original_sales_order_id = $sales_order_id;
				$sales_order_combine_mapping->combined_sales_order_id = $co['id'];
				$sales_order_combine_mapping->save();
				$sales_order_combine_mapping_id = mysql_insert_id();
				QDB::getConn()->execute('update sales_order set edit_flag=' . Q::ini('custom_flag/sales_order_edit_flag/edited/value') . ' where id=' . $co['id']);
				QDB::getConn()->execute('update sales_order set shipping_fee=shipping_fee+' . $co['shipping_fee'] . ', discount=discount+' . $co['discount'] . ' where id=' . $sales_order_id);
			}
			Sales_Order::updateOrder($sales_order_id);
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $judge_result['message']);
		}
	}
	
	/**
	 * 判断合并单是否能够被合并
	 * @param $sales_order_id
	 * @param $number
	 */
	static function judgeCombine($sales_order_id, $number)
	{
		$sales_order = Sales_Order::find('sales_order.id=?', $sales_order_id)
			->joinLeft('sales_order_customer_info', 'sales_order_customer_info.shop_buyer_id,sales_order_customer_info.fullname', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->asArray()->getOne();
		if ($sales_order['id'])
		{
			if (($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value')) && $sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/normal/value'))
			{
				foreach ($number as $n)
				{
					$combine_sales_order = Sales_Order::find('number=?', $n)
						->joinLeft('sales_order_customer_info', 'sales_order_customer_info.shop_buyer_id,sales_order_customer_info.fullname', 'sales_order_customer_info.sales_order_id=sales_order.id')
						->asArray()->getOne();
					if ($combine_sales_order)
					{
						if (($combine_sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $combine_sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value')) && $combine_sales_order['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/normal/value'))
						{
							if ($combine_sales_order['id'] == $sales_order['id'] || $combine_sales_order['shop_id'] != $sales_order['shop_id'] || $combine_sales_order['warehouse_id'] != $sales_order['warehouse_id'] || $combine_sales_order['shop_buyer_id'] != $sales_order['shop_buyer_id'] || $combine_sales_order['currency_id'] != $sales_order['currency_id'] || $combine_sales_order['fullname'] != $sales_order['fullname'])
							{
								return array('ack' => FAILURE, 'message' => 'combine sales order not meet the requirements');
							}
						}
						else
						{
							return array('ack' => FAILURE, 'message' => 'combine sales order status is incorrect');
						}
					}
					else
					{
						return array('ack' => FAILURE, 'message' => 'combine sales order is not exsits');
					}
				}
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'original sales order status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'original sales order is not exsit');
		}
	}
	
	static function EUBPostPackage($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		$soap_client = new SoapClient(Q::ini('custom_api/eub_api'), array('trace' => 1,'stream_context' => stream_context_create(array('http' => array('protocol_version' => 1.0)))));
//		$soap_client = new SoapClient(Q::ini('custom_api/eub_api'), array('proxy_host' => Q::ini('custom_api/proxy_host'), 'proxy_port' => Q::ini('custom_api/proxy_port')));
//		if (Q::ini('custom_api/proxy_status') == 'On')
//		{
//			$soap_client = new SoapClient(Q::ini('custom_api/eub_api'), array('proxy_host' => Q::ini('custom_api/proxy_host'), 'proxy_port' => Q::ini('custom_api/proxy_port')));
//		}
//		else
//		{
//			$soap_client = new SoapClient(Q::ini('custom_api/eub_api'));
//		}
		if ( ! $sales_order['tracking_number'])
		{
			if ($sales_order['send_method'] == Q::ini('custom_flag/sales_order_send_method/resend/value'))
			{
				$original_order = Sales_Order::find('id=?', $sales_order['resend_sales_order_id'])->asArray()->getOne();
				$recreate_result = Sales_Order::EUBRecreatePackage($original_order['tracking_number'], $sales_order['shop_id'], $soap_client);
				if ($recreate_result['ack'] == SUCCESS)
				{
					$tracking_number = $recreate_result['tracking_number'];
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $recreate_result['message']);
				}
			}
			else
			{
				$add_result = Sales_Order::EUBAddPackage($sales_order_id, $soap_client);
				if ($add_result['ack'] == SUCCESS)
				{
					$tracking_number = $add_result['tracking_number'];
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $add_result['message']);
				}
			}
			QDB::getConn()->execute('update sales_order set tracking_number=\'' . $tracking_number . '\' where id=' . $sales_order_id);
		}
		else
		{
			$tracking_number = $sales_order['tracking_number'];
		}
		$get_label_result = Sales_Order::EUBGetLabel($sales_order_id, $soap_client);
		if ($get_label_result['ack'] == SUCCESS)
		{
			if ($sales_order['send_method'] != Q::ini('custom_flag/sales_order_send_method/resend/value'))
			{
				$confirm_result = Sales_Order::EUBConfirmPackage($tracking_number, $sales_order['shop_id'], $soap_client);
				if ($confirm_result['ack'] == SUCCESS)
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $confirm_result['message']);
				}
			}
			else
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $get_label_result['message']);
		}
	}
	
	static function EUBRemovedPackage($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if (Q::ini('custom_api/proxy_status') == 'On')
		{
			$soap_client = new SoapClient(Q::ini('custom_api/eub_api'), array('proxy_host' => Q::ini('custom_api/proxy_host'), 'proxy_port' => Q::ini('custom_api/proxy_port')));
		}
		else
		{
			$soap_client = new SoapClient(Q::ini('custom_api/eub_api'));
		}
		if ($sales_order['tracking_number'])
		{
			if ($sales_order['shipping_method'] == Shipping_Method::getShippingMethodByCode('GZ_N_EUB'))
			{
				//删除旧的PDF
				$old_label_file = Q::ini('custom_system/eub_label_dir') . $sales_order['number'] . '.pdf';
				if (file_exists($old_label_file))
				{
					unlink($old_label_file);
				}
				
				//清除EUB信息
				$cancel_result = Sales_Order::EUBCancelPackage($sales_order['id'], $soap_client);
				QDB::getConn()->execute('update sales_order set tracking_number=\'\' where id=' . $sales_order_id);
				if ($cancel_result['ack'] == SUCCESS)
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $cancel_result['message']);
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'The order shipping method is error!');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'The order tracking number is NULL!');
		}
	}
	
	/**
	 * 添加EUB订单，同步订单数据到shipping tool
	 * @param $sales_order_id
	 */
	static function EUBAddPackage($sales_order_id, $soap_client)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		$shop_api = Shop_API_Ebay::find('shop_id=?', $sales_order['shop_id'])
			->joinLeft('shop', 'name', 'shop.id=shop_api_ebay.shop_id')
			->asArray()->getOne();
		$customer = Sales_Order_Customer_Info::find('sales_order_id=?', $sales_order_id)
			->joinLeft('country', 'code as country_code', 'country.en_name=sales_order_customer_info.country')
			->asArray()->getOne();
		$item = Sales_Order_Item::find('sales_order_id=? and gift_flag=?', $sales_order_id, Q::ini('custom_flag/sales_order_item_gift_flag/not/value'))
			->joinLeft('product_basic', 'number, declared_value, declared_name_cn, declared_name_en, weight', 'product_basic.id=sales_order_item.product_basic_id')
			->asArray()->getAll();
		$item_list = array();
		foreach ($item as $i)
		{
			$i['declared_name_cn'] = (in_array($i['declared_name_cn'], array('二极管', '开关', '微调电位器', '万能板', '电源', '保险管', '继电器，继电器座'))) ? '儿童玩具' : (in_array($i['declared_name_cn'], array('电容', '电压表', '电流表', '电阻')) ? '文具' : (($i['declared_name_cn'] == '手表') ? '手环' : $i['declared_name_cn']));
			$i['declared_name_en'] = (in_array(strtolower($i['declared_name_en']), array('diode', 'switch', 'potentiometer', 'circuit board', 'Power supply', 'fuse', 'relay'))) ? 'Toys' : (in_array(strtolower($i['declared_name_en']), array('capacitor', 'meter', 'resistor')) ? 'stationery' : ((strtolower($i['declared_name_en']) == 'watch') ? 'bracelet' : $i['declared_name_en']));
			$this_weight = floatval($i['weight']) ? $i['weight'] / 1000 : 0.025;
			$item_list[] = array(
				'EBayItemID' => $i['shop_item_id'],
				'EBayTransactionID' => $i['shop_transaction_id'],
				'EBayBuyerID' => $customer['shop_buyer_id'],
				'EBaySiteID' => '',
				'OrderSalesRecordNumber' => '',
				'PaymentDate' => $sales_order['paid_time'] ? substr($sales_order['paid_time'], 0, 10) : substr($sales_order['sales_time'], 0, 10),
				'ReceivedAmount' => $sales_order['amount'],
				'SalesRecordNumber' => '',
				'SoldDate' => substr($sales_order['sales_time'], 0, 10),
				'SoldPrice' => $i['sales_price'],
				'SoldQTY' => $i['quantity'],
				'PostedQTY' => $i['quantity'],
				'SKU' => array(
					'SKUID' => $i['number'],
					'DeclaredValue' => floatval(($i['declared_value']>20) ? 20 : $i['declared_value']),
					'Weight' => $this_weight,
					'CustomsTitle' => $i['declared_name_cn'] ? $i['declared_name_cn'] : '',
					'CustomsTitleEN' => $i['declared_name_en'] ? $i['declared_name_en'] : '',
					'OriginCountryName' => 'China',
					'OriginCountryCode' => 'CN'
				),
			);
		}
		$package = array(
			'APIDevUserID'		=> Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
			'APISellerUserToken'=> $shop_api['token'],
			'APISellerUserID'	=> $shop_api['name'],
			'AppID' 			=> Q::ini('custom_api/X-EBAY-API-APP-NAME'),
			'AppCert' 			=> Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
			'MessageID'			=> $sales_order['number'],
			'Version'			=> '4.0.0',
			'Carrier' 			=> 'CNPOST',
			'Service' 			=> 'EPACK',
			'OrderDetail'		=> array(
				'EMSPickUpType' => '1',
				'PickUpAddress' => array(
					'Contact' => '何文峰',
					'Company' => '自营',
					'Street' => '中国广东省广州市白云区云宵路3号航空邮件处理中心2楼',
					'District' => '440106',
					'City' => '440100',
					'Province' => '440000',
					'Postcode' => '510000',
					'CountryCode' => 'CN',
					'Email' => 'zhangtieyao8351@126.com',
					'Mobile' => '18988932428',
					'Phone' => '18988932428'
				),
				'ShipFromAddress' => array(
					'Contact' => 'wenfeng he',
					'Company' => 'zi ying',
					'Street' => '2 FLOOR,AIR MAIL PROCESSING CENTER ,#3 YUNXIAO ROAD',
					'District' => 'TianHe District',
					'City' => 'Guangzhou',
					'Province' => 'GUANGDONG',
					'Postcode' => '510000',
					'CountryCode' => 'CN',
					'Email' => 'zhangtieyao8351@126.com',
					'Mobile' => '18988932428',
				),
				'ShipToAddress' => array(
					'Contact' => $customer['fullname'],
					'Street' => $customer['street1'] . ' ' . $customer['street2'],
					'City' => $customer['city'],
					'Province' => $customer['state'],
					'CountryCode' => $customer['country_code'],
					'Postcode' => $customer['zip'],
					'Phone' => $customer['phone'],
					'Email' => $customer['email']
				),
				'ReturnAddress' => array(
					'Contact' => 'wenfeng he',
					'Company' => 'zi ying',
					'Street' => '2 FLOOR,AIR MAIL PROCESSING CENTER ,#3 YUNXIAO ROAD',
					'City' => 'Guangzhou',
					'Province' => 'GUANGDONG',
					'Postcode' => '510000',
					'CountryCode' => 'CN',
					'Email' => 'zhangtieyao8351@126.com',
					'Mobile' => '18988932428',
				),
				'ItemList' => array('Item' => $item_list)
			)
		);
		ini_set("soap.wsdl_cache_enabled", "0");
		$result = $soap_client->AddAPACShippingPackage(array('AddAPACShippingPackageRequest'=>$package));
		if ($result->AddAPACShippingPackageResult->Ack == 'Success')
		{
			return array('ack' => SUCCESS, 'message' => '', 'tracking_number' => $result->AddAPACShippingPackageResult->TrackCode);
		}
		else
		{
			if (is_array($result->AddAPACShippingPackageResult->NotificationList->Notification))
			{
				$notification = $result->AddAPACShippingPackageResult->NotificationList->Notification;
			}
			else
			{
				$notification = array($result->AddAPACShippingPackageResult->NotificationList->Notification);
			}
			$message = array();
			foreach ($notification as $n)
			{
				$message[] = $n->Message;
			}
			return array('ack' => FAILURE, 'message' => implode(';', $message));
		}
	}
	
	/**
	 * 获取包裹当前状态
	 * @param $tracking_number
	 * @param $shop_id
	 */
	static function EUBGetPackageStatus($tracking_number, $shop_id, $soap_client)
	{
		$shop_api = Shop_API_Ebay::find('shop_id=?', $shop_id)
			->joinLeft('shop', 'name', 'shop.id=shop_api_ebay.shop_id')
			->asArray()->getOne();
		$get_status_request = array(
			'APIDevUserID'		=> Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
			'APISellerUserToken'=> $shop_api['token'],
			'APISellerUserID'	=> $shop_api['name'],
			'AppID' 			=> Q::ini('custom_api/X-EBAY-API-APP-NAME'),
			'AppCert' 			=> Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
			'MessageID'			=> '',
			'Version'			=> '4.0.0',
			'Carrier' 			=> 'CNPOST',
			'TrackCode'			=> $tracking_number
		);
		$get_status_result = $soap_client->GetAPACShippingPackageStatus(array('GetAPACShippingPackageStatusRequest' => $get_status_request));
		if ($get_status_result->GetAPACShippingPackageStatusResult->Ack == 'Success')
		{
			$package_status = $get_status_result->GetAPACShippingPackageStatusResult->Status;
			return array('ack' => SUCCESS, 'message' => '', 'status' => $package_status);
		}
		else
		{
			if (is_array($get_status_result->GetAPACShippingPackageStatusResult->NotificationList->Notification))
			{
				$notification = $get_status_result->GetAPACShippingPackageStatusResult->NotificationList->Notification;
			}
			else
			{
				$notification = array($get_status_result->GetAPACShippingPackageStatusResult->NotificationList->Notification);
			}
			$message = array();
			foreach ($notification as $n)
			{
				$message[] = $n->Message;
			}
			return array('ack' => FAILURE, 'message' => implode(';', $message));
		}
	}
	
	/**
	 * EUB申请重发
	 * @param $sales_order_id
	 */
	static function EUBRecreatePackage($tracking_number, $shop_id, $soap_client)
	{
		$shop_api = Shop_API_Ebay::find('shop_id=?', $shop_id)
			->joinLeft('shop', 'name', 'shop.id=shop_api_ebay.shop_id')
			->asArray()->getOne();
		$resend_request = array(
			'APIDevUserID'		=> Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
			'APISellerUserToken'=> $shop_api['token'],
			'APISellerUserID'	=> $shop_api['name'],
			'AppID' 			=> Q::ini('custom_api/X-EBAY-API-APP-NAME'),
			'AppCert' 			=> Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
			'MessageID'			=> '',
			'Version'			=> '4.0.0',
			'Carrier' 			=> 'CNPOST',
			'TrackCode'			=> $tracking_number
		);
		$resend_result = $soap_client->RecreateAPACShippingPackage(array('RecreateAPACShippingPackageRequest' => $resend_request));
		if ($resend_result->RecreateAPACShippingPackageResult->Ack == 'Success')
		{
			$track_code = $resend_result->RecreateAPACShippingPackageResult->TrackCode;
			return array('ack' => SUCCESS, 'message' => '', 'tracking_number' => $track_code);
		}
		else
		{
			if (is_array($resend_result->RecreateAPACShippingPackageResult->NotificationList->Notification))
			{
				$notification = $resend_result->RecreateAPACShippingPackageResult->NotificationList->Notification;
			}
			else
			{
				$notification = array($resend_result->RecreateAPACShippingPackageResult->NotificationList->Notification);
			}
			$message = array();
			foreach ($notification as $n)
			{
				$message[] = $n->Message;
			}
			return array('ack' => FAILURE, 'message' => implode(';', $message));
		}
	}
	
	/**
	 * 取消并删除交运前的订单
	 * @param $sales_order_id
	 */
	static function EUBCancelPackage($sales_order_id, $soap_client)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['tracking_number'])
			{
				$shop_api = Shop_API_Ebay::find('shop_id=?', $sales_order['shop_id'])
					->joinLeft('shop', 'name', 'shop.id=shop_api_ebay.shop_id')
					->asArray()->getOne();
				$cancel_request = array(
					'APIDevUserID'		=> Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
					'APISellerUserToken'=> $shop_api['token'],
					'APISellerUserID'	=> $shop_api['name'],
					'AppID' 			=> Q::ini('custom_api/X-EBAY-API-APP-NAME'),
					'AppCert' 			=> Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
					'MessageID'			=> '',
					'Version'			=> '4.0.0',
					'Carrier' 			=> 'CNPOST',
					'TrackCode'			=> $sales_order['tracking_number']
				);
				$cancel_result = $soap_client->CancelAPACShippingPackage(array('CancelAPACShippingPackageRequest' => $cancel_request));
				if ($cancel_result->CancelAPACShippingPackageResult->Ack == 'Success')
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{	
					if (is_array($cancel_result->CancelAPACShippingPackageResult->NotificationList->Notification))
					{
						$notification = $cancel_result->CancelAPACShippingPackageResult->NotificationList->Notification;
					}
					else
					{
						$notification = array($cancel_result->CancelAPACShippingPackageResult->NotificationList->Notification);
					}
					$message = array();
					foreach ($notification as $n)
					{
						$message[] = $n->Message;
					}
					return array('ack' => FAILURE, 'message' => implode(';', $message));
				}
			}
		}
	}
	
	/**
	 * 获取EUB标签流并保存pdf文件
	 * @param $sales_order_id
	 */
	static function EUBGetLabel($sales_order_id, $soap_client)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['tracking_number'])
			{
				$shop_api = Shop_API_Ebay::find('shop_id=?', $sales_order['shop_id'])
					->joinLeft('shop', 'name', 'shop.id=shop_api_ebay.shop_id')
					->asArray()->getOne();
				$label_request = array(
					'APIDevUserID'		=> Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
					'APISellerUserToken'=> $shop_api['token'],
					'APISellerUserID'	=> $shop_api['name'],
					'AppID' 			=> Q::ini('custom_api/X-EBAY-API-APP-NAME'),
					'AppCert' 			=> Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
					'MessageID'			=> '',
					'Version'			=> '4.0.0',
					'Carrier' 			=> 'CNPOST',
					'PageSize'			=> '1',
					'TrackCode'			=> $sales_order['tracking_number']
				);
				$label_result = $soap_client->GetAPACShippingLabel(array('GetAPACShippingLabelRequest' => $label_request));
				if ($label_result->GetAPACShippingLabelResult->Ack == 'Success')
				{
					file_put_contents(Q::ini('custom_system/eub_label_dir') . $sales_order['number'] . '.pdf', $label_result->GetAPACShippingLabelResult->Label);
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $label_result->GetAPACShippingLabelResult->Message);
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'tracking number is not exists');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * EUB交运
	 * @param $tracking_number
	 * @param $shop_id
	 */
	static function EUBConfirmPackage($tracking_number, $shop_id, $soap_client)
	{
		$shop_api = Shop_API_Ebay::find('shop_id=?', $shop_id)
			->joinLeft('shop', 'name', 'shop.id=shop_api_ebay.shop_id')
			->asArray()->getOne();
		$confirm_request = array(
			'APIDevUserID'		=> Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
			'APISellerUserToken'=> $shop_api['token'],
			'APISellerUserID'	=> $shop_api['name'],
			'AppID' 			=> Q::ini('custom_api/X-EBAY-API-APP-NAME'),
			'AppCert' 			=> Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
			'MessageID'			=> '',
			'Version'			=> '4.0.0',
			'Carrier' 			=> 'CNPOST',
			'TrackCode'			=> $tracking_number
		);
		$confirm_result = $soap_client->ConfirmAPACShippingPackage(array('ConfirmAPACShippingPackageRequest' => $confirm_request));
		if ($confirm_result->ConfirmAPACShippingPackageResult->Ack == 'Success')
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			if (is_array($confirm_result->ConfirmAPACShippingPackageResult->NotificationList->Notification))
			{
				$notification = $confirm_result->ConfirmAPACShippingPackageResult->NotificationList->Notification;
			}
			else
			{
				$notification = array($confirm_result->ConfirmAPACShippingPackageResult->NotificationList->Notification);
			}
			$message = array();
			foreach ($notification as $n)
			{
				$message[] = $n->Message;
			}
			return array('ack' => FAILURE, 'message' => implode(';', $message));
		}
	}
	
	/**
	 * 国际EUB同步
	 * @param $sales_order_id
	 */
	static function IEUBPostPackage($sales_order_id)
	{
		$judge_result = Sales_Order::judgeIEUBPostPackage($sales_order_id);
		if ($judge_result['ack'] == SUCCESS)
		{
			$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
			$tracking_number = $sales_order['tracking_number'];
			if ( ! $tracking_number)
			{
				$add_package_result = Sales_Order::IEUBAddPackage($sales_order_id);
				if ($add_package_result['ack'] == SUCCESS)
				{
					$tracking_number = $add_package_result['tracking_number'];
					QDB::getConn()->execute('update sales_order set tracking_number=\'' . $tracking_number . '\' where id=' . $sales_order_id);
					sleep(5);
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $add_package_result['message']);
				}
			}
			$get_label_result = Sales_Order::IEUBGetLabel($sales_order_id);
			if ($get_label_result['ack'] == SUCCESS)
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $get_label_result['message']);
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $judge_result['message']);
		}
	}
	
	/**
	 * 判断国际EUB是否可以同步
	 * @param unknown_type $sales_order_id
	 */
	static function judgeIEUBPostPackage($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['shipping_method'] == Shipping_Method::getShippingMethodByCode('GZ_N_IEUB'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'shipping method is not iEUB');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 国际EUB添加订单
	 * @param $sales_order_id
	 */
	static function IEUBAddPackage($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		$customer_info = Sales_Order_Customer_Info::find('sales_order_id=?', $sales_order_id)
			->joinLeft('country', 'code as country_code', 'country.en_name=sales_order_customer_info.country')
			->asArray()->getOne();
		$item = Sales_Order_Item::find('sales_order_id=? and gift_flag=?', $sales_order_id, Q::ini('custom_flag/sales_order_item_gift_flag/not/value'))
			->joinLeft('product_basic', 'number, declared_value, declared_name_cn, declared_name_en, weight', 'product_basic.id=sales_order_item.product_basic_id')
			->asArray()->getAll();
		$xml =  '<?xml version="1.0" encoding="UTF-8"?>';
		$xml .= '<orders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
		$xml .= '<order>';
		$xml .= '<orderid>' . $sales_order['number'] . '</orderid>';
		$xml .= '<customercode>' . Q::ini('custom_api/ieub_api_customercode') . '</customercode>';
		$xml .= '<clcttype>0</clcttype>';
		$xml .= '<pod>false</pod>';
		$xml .= '<untread>Returned</untread>';
		$xml .= '<printcode>01</printcode>';
		$xml .= '<volweight>2</volweight>';
		$xml .= '<sender>';
		$xml .= 	'<name>xiongjin</name>';
		$xml .= 	'<postcode>518129</postcode>';
		$xml .= 	'<phone>0755-89489177</phone>';
		$xml .= 	'<mobile>15874133284</mobile>';
		$xml .= 	'<country>CN</country>';
		$xml .= 	'<province>440000</province>';
		$xml .= 	'<city>440300</city>';
		$xml .= 	'<county>440307</county>';
		$xml .= 	'<company>Zongteng wangluojishuyouxiangongsi</company>';
		$xml .= 	'<street>bantianjiedaowuhedadaonan49haojinfanghuagongyequ8dong109 BZ</street>';
		$xml .= 	'<email>jewel@yesurprise.com</email>';
		$xml .= '</sender>';
		$xml .= '<receiver>';
		$xml .= 	'<name>' . $customer_info['fullname'] . '</name>';
		$xml .= 	'<postcode>' . $customer_info['zip'] . '</postcode>';
		$xml .= 	'<phone>' . $customer_info['phone'] . '</phone>';
		$xml .= 	'<country>' . $customer_info['country_code'] . '</country>';
		$xml .= 	'<province>' . $customer_info['state'] . '</province>';
		$xml .= 	'<city>' . $customer_info['city'] . '</city>';
		$xml .= 	'<street>' . $customer_info['street1'] . ' ' . $customer_info['street2'] . '</street>';
		$xml .= '</receiver>';
		$xml .= '<collect>';
		$xml .= 	'<name>熊进</name>';
		$xml .= 	'<postcode>518129</postcode>';
		$xml .= 	'<phone>0755-89489177</phone>';
		$xml .= 	'<mobile>15874133284</mobile>';
		$xml .= 	'<country>CN</country>';
		$xml .= 	'<province>440000</province>';
		$xml .= 	'<city>440300</city>';
		$xml .= 	'<county>440307</county>';
		$xml .= 	'<company>纵腾网络技术有限公司</company>';
		$xml .= 	'<street>深圳市龙岗区坂田街道五河大道南49号金方华工业区8栋109 BZ</street>';
		$xml .= 	'<email>jewel@yesurprise.com</email>';
		$xml .= '</collect>';
		$xml .= '<items>';
		foreach ($item as $i)
		{
			$xml .= '<item>';
			$xml .= 	'<cnname>' . ($i['declared_name_cn'] ? $i['declared_name_cn'] : '') . '</cnname>';
			$xml .= 	'<enname>' . ($i['declared_name_en'] ? $i['declared_name_en'] : '') . '</enname>';
			$xml .= 	'<count>' . $i['quantity'] . '</count>';
			$xml .= 	'<weight>' . (floatval($i['weight']) ? (sprintf('%.3f', $i['weight'] / 1000)) : 0.025) . '</weight>';
			$xml .= 	'<delcarevalue>' . (floatval(($i['declared_value'] > 20) ? 20 : $i['declared_value'])) . '</delcarevalue>';
			$xml .= 	'<origin>CN</origin>';
			$xml .= '</item>';
		}
		$xml .= '</items>';
		$xml .= '</order>';
		$xml .= '</orders>';
		$result = Helper_BSS_API::iEUBAPICall(Q::ini('custom_api/ieub_api_uri_prefix') . 'partner/api/public/p/order', 'POST', $xml);
		if ($result)
		{
			$result = simplexml_load_string($result);
			if (isset($result->mailnum[0]))
			{
				$tracking_number = (string)$result->mailnum[0];
				return array('ack' => SUCCESS, 'message' => '', 'tracking_number' => $tracking_number);
			}
			else
			{
				return array('ack' => FAILURE, 'message' => (string)$result->description[0]);
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '返回结果为空');
		}
	}
	
	/**
	 * 国际EUB获取地址单Label
	 * @param unknown_type $sales_order_id
	 */
	static function IEUBGetLabel($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		$uri = Q::ini('custom_api/ieub_api_label_url_prefix') . md5(Q::ini('custom_api/ieub_api_authenticate') . $sales_order['tracking_number']) . '/' . $sales_order['tracking_number'] . '.pdf';
		$response = Helper_BSS_API::iEUBAPICall($uri, 'GET', '');
		file_put_contents(Q::ini('custom_system/eub_label_dir') . $sales_order['number'] . '.pdf', $response);
		if (filesize(Q::ini('custom_system/eub_label_dir') . $sales_order['number'] . '.pdf') > 10240)
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			unlink(Q::ini('custom_system/eub_label_dir') . $sales_order['number'] . '.pdf');
			return array('ack' => FAILURE, 'message' => 'get label failure, click again');
		}
	}
	
	/**
	 * 清除国际EUB信息
	 * @param $sales_order_id
	 */
	static function IEUBRemovedPackage($sales_order_id)
	{
		$judge_result = Sales_Order::judgeIEUBRemovedPackage($sales_order_id);
		if ($judge_result['ack'] == SUCCESS)
		{
			QDB::getConn()->execute('update sales_order set tracking_number=\'\' where id=' . $sales_order_id);
			if (is_file($judge_result['label_name']))
			{
				unlink($judge_result['label_name']);
			}
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			return $judge_result;
		}
	}
	
	/**
	 * 判断是否可以清楚国际EUB信息
	 * @param $sales_order_id
	 */
	static function judgeIEUBRemovedPackage($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['shipping_method'] == Shipping_Method::getShippingMethodByCode('GZ_N_IEUB'))
			{
				if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value'))
				{
					return array('ack' => SUCCESS, 'message' => '', 'label_name' => Q::ini('custom_system/eub_label_dir') . $sales_order['number'] . '.pdf');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => 'order status is incorrect');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'order is not IEUB');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'orde is not exists');
		}
	}
	
	/**
	 * 查询出指定的出库单信息
	 * @param $sales_order_id
	 */
	static function judgeCK1OutStoreAudit($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=' . $sales_order_id)->asArray()->getOne();
		if ($sales_order['tracking_number'])
		{
			$param = array(
				'Token' => Q::ini('custom_api/ck1_express_api_token'),
				'UserKey' => Q::ini('custom_api/ck1_express_api_key'),
				'MessageID' => '',
				'Sign' => $sales_order['tracking_number'],
				'Submit' => false
			);
			try
			{
				$soap_client = new SoapClient(Q::ini('custom_api/express_wsdl'));
				$result = $soap_client->OutStoreGetPackage(array('request' => $param));
			}
			catch (Exception $e)
			{
				dump($e);exit;
				return array('ack' => FAILURE, 'message' => 'get exception');
			}
			if ($result->OutStoreGetPackageResult->Ack == 'Success')
			{
				$outstore_state = $result->OutStoreGetPackageResult->PackageDetail->State;
				if ($outstore_state == 'Shipped')
				{
					return array('ack' => SUCCESS, 'message' => '', 'tracking_number' => $result->OutStoreGetPackageResult->PackageDetail->TrackingNumber);
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': overseas outstore status is ' . $outstore_state);
				}
			}
			else
			{
				dump($result->OutStoreGetPackageResult->Message);
				dump($param);exit;
				return array('ack' => FAILURE, 'message' => $result->OutStoreGetPackageResult->Message);
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'overseas outstore is not synchronized!');
		}
	}
	
	/**
	 * 同步香港DHL（PKG）
	 * @param $sales_order_ids
	 * @param $type
	 */
	static function HKExpressSync($sales_order_ids)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			->joinLeft('sales_order_customer_info', 'fullname, phone, street1, street2, city, zip, state, country', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
			->asArray()->getAll();
		$message = array();
		foreach ($sales_orders as $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'declared_value, declared_name_en, declared_name_cn, number as product_number, weight', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			if ($so['country_code'])
			{
				$weight = $quantity = $declared_value = 0;
				foreach ($item as $i)
				{
					$quantity += $i['quantity'];
					$declared_value += $i['declared_value'];
					$weight += $i['weight'];
				}
				$param = array(
					'parcelGenericOrderRequest' => array(
						'customer' => array(
							'custAcctNo' => Q::ini('custom_api/HK_api_ucode'),
							'userNm' => Q::ini('custom_api/HK_api_uname'),
							'password' => Q::ini('custom_api/HK_api_upasswd')
						),
						'order' => array(
							'orderItemList' => array(
								'orderItemContentList' => array(
									'exportCd' => $item[0]['product_number'],
									'exportDesc' => $item[0]['declared_name_cn'],
									'exportQty' => $quantity,
									'unitPrice' => $declared_value,
									'weight' => $weight,
									'hsCode' => $item[0]['product_number'],
									'ctryOfMftr' => 'CN',
								),
								'product' => 'GM Packet',
								'serviceLevel' => 'Standard',
								'custRef' => 'HKBAO' . $so['number'],
								'consgneeNm' => $so['fullname'],
								'consgneeAddr1' => $so['street1'],
								'consgneeAddr2' => $so['street2'],
								'consgneeTownCity' => $so['city'],
								'consgneeState' => $so['state'],
								'consgneePostalCd' => $so['zip'],
								'consgneeCountryCd' => $so['country_code'],
								'totalPrice' => $declared_value*$quantity,
								'totalWeight' => $weight,
								'origin' => 'CN',
								'declaredCurrCd' => 'USD',
								'shipperNm' => 'Baozhou',
								'shipperAddr1' => 'GaoPu Road',
								'shipperAddr2' => 'Guangzhou Internet Industrial Park',
								'shipperTownCity' => 'TianHe District GuangZhou',
								'shipperState' => 'GuangDong',
								'shipperPostalCd' => '510000',
								'shipperCountryCd' => 'CN',
								'shipmentDesc' => $item[0]['declared_name_en'],
							),
							'pickupInfo' => 'Customer Drop Off',
							'location' => 'HKG',
							'dropOffDt' => date('d-M-Y', time()+3600*24)
						)
					)
				);
				try
				{
					if (Q::ini('custom_api/proxy_status') == 'On')
					{
						$client = new SoapClient(Q::ini('custom_api/HK_api_uri'), array('proxy_host' => Q::ini('custom_api/proxy_host'), 'proxy_port' => Q::ini('custom_api/proxy_port')));
					}
					else
					{
						$client = new SoapClient(Q::ini('custom_api/HK_api_uri'));
					}
					$result = $client->createGenericRouteOrder($param);
					if (! empty($result->return->success))
					{
						QDB::getConn()->execute('update sales_order set lsp_number=\'' . 'HKBAO' . $so['number'] . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/HK/value') . '\' where id=' . $so['id']);
					}
					else
					{
						$message[] = $so['number'] . ': ' . $result->return->errorMsg;
					}
				}
				catch(Exception $e)
				{
					echo "<h2>Exception Error!</h2>";
					echo $e->getMessage();
					continue;
				}
				catch(SoapFault $e)
				{
					echo "<h2>SoapFault Error!</h2>";
					echo $e->getMessage();
					continue;
				}
			}
			else
			{
				$message[] = $so['number'] . ': 同步失败，国家二字码为空！';
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 同步均辉
	 * @param $sales_order_ids
	 * @param $type
	 */
	static function JHExpressSync($sales_order_ids, $type)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			->joinLeft('sales_order_customer_info', 'fullname, phone, street1, street2, city, zip, state', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
			->asArray()->getAll();
		foreach ($sales_orders as $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'declared_value, declared_name_cn, declared_name_en', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			if ($so['country_code'])
			{
				$quantity = 0;
				$declared_value = 0;
				foreach ($item as $i)
				{
					$quantity += $i['quantity'];
					$declared_value += $i['declared_value'];
				}
				$params = array(
					'in0' => Q::ini('custom_api/JH_api_uname'),
					'in1' => Q::ini('custom_api/JH_api_upasswd'),
					'in2' => $so['number'],
					'in3' => $so['weight']/1000,
					'in4' => $quantity,
					'in5' => $item[0]['declared_name_en'],
					'in6' => $so['fullname'],
					'in7' => $so['phone'],
					'in8' => $so['country_code'],
					'in9' => $so['street1'] .' '. $so['street2'],
					'in10' => $type,
					'in11' => $so['city'],
					'in12' => $declared_value,
					'in13' => $so['state'],
					'in14' => $so['zip']
				);
				if($params['in6']) $params['in6'] = substr($params['in6'],0,20);
				if($params['in9']) $params['in9'] = substr($params['in9'],0,60);
				if($params['in11']) $params['in11'] = substr($params['in11'],0,20);
				while(1)
				{
					try
					{
						if (Q::ini('custom_api/proxy_status') == 'On')
						{
							$client = new SoapClient(Q::ini('custom_api/JH_api_uri'), array('proxy_host' => Q::ini('custom_api/proxy_host'), 'proxy_port' => Q::ini('custom_api/proxy_port')));
						}
						else
						{
							$client = new SoapClient(Q::ini('custom_api/JH_api_uri'));
						}
						$result = $client->addPreAwbEms($params);
					}
					catch(Exception $e)
					{
						echo "<h2>Exception Error!</h2>";
						echo $e->getMessage();
						continue;
					}
					catch(SoapFault $e)
					{
						echo "<h2>SoapFault Error!</h2>";
						echo $e->getMessage();
						continue;
					}
					break;
				}
				$message = explode(',', $result->out);
				if (trim($message[0]) == 'Success')
				{
					$number = trim(substr($message[1], 12));
					$tracking_number = trim(substr($message[2], 9));
					if ($type == Q::ini('custom_flag/JH_order_type/R_DHL_Package/value'))
					{
						QDB::getConn()->execute('update sales_order set tracking_number=\''. $tracking_number . '\', lsp_number=\'' . $number . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/JH/value') . '\' where id=' . $so['id']);
					}
					else
					{
						QDB::getConn()->execute('update sales_order set lsp_number=\'' . $number . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/JH/value') . '\' where id=' . $so['id']);
					}
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $message[0]);
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $so['number'] . ': country code is not exists');
			}
		}
		return array('ack' => SUCCESS, 'message' => '');
	}
	
	static function MCExpressSync($sales_order_ids, $type)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			->joinLeft('sales_order_customer_info', 'fullname, phone, street1, street2, city, zip, state, country', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
			->asArray()->getAll();
		$params = array(
			'userName' => Q::ini('custom_api/MC_api_uname'),
			'pwd' => '0228949',
		);
		foreach ($sales_orders as $key => $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'declared_value, declared_name_en, weight', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			$quantity = 0;
			foreach ($item as $i)
			{
				$quantity += $i['quantity'];
			}
			$params['record'][] = array(
				'orderReference' => $so['number'],
				'orderWritename' => $so['fullname'],
				'orderWriteaddress' => $so['street1'] . ', ' . $so['street2'] . ', ' . $so['city'] . ', ' . $so['state'],
				'orderWritetel' => $so['phone'],
				'orderDestination' => isset($so['country_code']) ? $so['country_code'] : $so['country'],
				'orderCode' => $so['zip'],
				'orderQuantity' => '1',
				'orderWrite' => sprintf('%.2f', ($so['weight']/1000)),
				'orderGoodsname' => $item[0]['declared_name_en'],
				'column2' => $quantity,
				'orderWorth' => $item[0]['declared_value'],
				'column5' => 'USD',
				'orderContent' => '',
				'orderType' => $type,
				'goodsAlias' => '',
			);
		}
		$params = json_encode($params);
		$data['jsonContent'] = $params;
		$url = Q::ini('custom_api/MC_api_uri');
		$ch = curl_init();
		$timeout = 300;
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		if (Q::ini('custom_api/proxy_status') == 'On')
		{
			curl_setopt($ch, CURLOPT_PROXY, Q::ini('custom_api/proxy_host') . ':' . Q::ini('custom_api/proxy_port'));
		}
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
		$handles = curl_exec($ch);
		curl_close($ch);
		$result = json_decode($handles, true);
		if ($result['statusCode'] == SUCCESS)
		{
			foreach ($result['record'] as $key => $rr)
			{
				QDB::getConn()->execute('update sales_order set tracking_number=\''. $rr['trackCode'] . '\', lsp_number=\'' . $rr['trackCode'] . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/MC/value') . '\' where number=\'' . $key . '\'');
			}
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			dump($result['record']);
			return array('ack' => FAILURE, 'message' => 'statusCode is ' . $result['statusCode']);
		}
	}
	
	static function SFCExpressSync($sales_order_ids, $type)
	{
		
		$sales_order = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			->joinLeft('sales_order_customer_info', 'country, state, city, fullname, street1, street2, zip, phone, email', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->asArray()->getAll();
		$message = '';
		foreach ($sales_order as $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'declared_value, declared_name_en', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			if ($so['country'])
			{
				$quantity = $declared_value = 0;
				foreach ($item as $i)
				{
					$quantity += $i['quantity'];
					$declared_value += $i['declared_value']*$i['quantity'];
				}
				$declared_value = ($declared_value >= 22) ? 22 : (($so['country'] == 'Germany') ? 15 : $declared_value);
				$detailWorth = floor($declared_value/$quantity*10)/10;
				$declared_value = $detailWorth*$quantity;
				$parameter = array(
					'HeaderRequest' => array(
						'appKey' => Q::ini('custom_api/SFC_api_appkey'),
						'token' => Q::ini('custom_api/SFC_api_token'),
						'userId' => Q::ini('custom_api/SFC_api_userid')
					),
					'addOrderRequestInfo' => array(
						'customerOrderNo' => empty($so['tracking_number']) ? $so['number'] : $so['tracking_number'],
						'shipperAddressType' => 1,
						'shippingMethod' => $type,
						'recipientCountry' => $so['country'],
						'recipientState' => $so['state'],
						'recipientCity' => $so['city'],
						'recipientName' => $so['fullname'],
						'recipientAddress' => $so['street1'] . ' ' . $so['street2'],
						'recipientZipCode' => $so['zip'],
						'recipientPhone' => $so['phone'],
						'recipientEmail' => $so['email'],
						'goodsDescription' => $item[0]['declared_name_en'],
						'goodsQuantity' => $quantity,
						'goodsDeclareWorth' => $declared_value,
						'orderStatus' => 'confirmed',
						'goodsDetails' => array(
							array(
								'detailDescription' => $item[0]['declared_name_en'],
								'detailQuantity' => $quantity,
								'detailWorth' => $detailWorth
							),
						),
					),
				);
				try
				{
					if (Q::ini('custom_api/proxy_status') == 'On')
					{
						$client = new SoapClient(Q::ini('custom_api/SFC_api_uri'), array('proxy_host' => Q::ini('custom_api/proxy_host'), 'proxy_port' => Q::ini('custom_api/proxy_port')));
					}
					else
					{
						$client = new SoapClient(Q::ini('custom_api/SFC_api_uri'));
					}
					$result = $client->addOrder($parameter);
				}
				catch(Exception $e)
				{
					echo "<h2>Exception Error!</h2>";
					echo $e->getMessage();
					continue;
				}
				catch(SoapFault $e)
				{
					echo "<h2>SoapFault Error!</h2>";
					echo $e->getMessage();
					continue;
				}
				if ($result->orderActionStatus == 'Y')
				{
					QDB::getConn()->execute('update sales_order set tracking_number=\''. $result->orderCode . '\', lsp_number=\'' . $result->orderCode . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/SFC/value') . '\' where id=' . $so['id']);
					$tracking_parameter = array(
						'HeaderRequest' => array(
							'appKey' => Q::ini('custom_api/SFC_api_appkey'),
							'token' => Q::ini('custom_api/SFC_api_token'),
							'userId' => Q::ini('custom_api/SFC_api_userid')
						),
						'searchOrderRequestInfo' => array('orderCode' => $result->orderCode)
					);
					try
					{
						$tracking_result = $client->searchOrder($tracking_parameter);
					}
					catch(Exception $e)
					{
						echo "<h2>Exception Error!</h2>";
						echo $e->getMessage();
						continue;
					}
					catch(SoapFault $e)
					{
						echo "<h2>SoapFault Error!</h2>";
						echo $e->getMessage();
						continue;
					}
					if (! empty($tracking_result->orderInfo->trackNumber))
					{
						QDB::getConn()->execute('update sales_order set tracking_number=\''. $tracking_result->orderInfo->trackNumber . '\' where id=' . $so['id']);
					}
				}
				else
				{
					$message .= $so['number'] . '：' . $result->note . ';';
				}
			}
		}
		return array('ack' => SUCCESS, 'message' => $message);
	}
	
	static function FPXExpressSync($sales_order_ids, $type)
	{
		$sales_order = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			->joinLeft('sales_order_customer_info', 'fullname, phone, email, street1, street2, city, zip, state, country', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
			->asArray()->getAll();
		$message = '';
		foreach ($sales_order as $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
					->joinLeft('product_basic', 'declared_value, declared_name_cn, declared_name_en', 'product_basic.id=sales_order_item.product_basic_id')
					->asArray()->getAll();
			if ($so['country_code'])
			{
				$declareInvoice = array();
				foreach ($item as $k => $i)
				{
					$declareInvoice[$k] = array(
						'declarePieces' => $i['quantity'],
						'name' => $i['declared_name_cn'],
						'eName' => $i['declared_name_en'],
						'unitPrice' => sprintf('%.2f', $i['declared_value']),
					);
				}
				$createOrderArray[0] = array(
					'orderNo' => $so['number'],
					'returnSign' => in_array($type, array('C1', 'C2', 'A6', 'A7')) ? 'N' : 'Y',
					'customerWeight' => sprintf('%.2f', ($so['estimated_weight']/1000)),
					'trackingNumber' => '',
					'productCode' => $type,
					'destinationCountryCode' => $so['country_code'],
					'consigneeName' => $so['fullname'],
					'street' => $so['street1'] . ' ' . $so['street2'],
					'city' => $so['city'],
					'stateOrProvince' => $so['state'], 
					'consigneePostCode' => $so['zip'],
					'consigneeTelephone' => $so['phone'],
					'consigneeEmail' => $so['email'],
					'declareInvoice' => $declareInvoice
				);
				$params = array(
					'arg0' => Q::ini('custom_api/4PX_api_token'),
					'arg1' => $createOrderArray
				);
				try
				{
					if (Q::ini('custom_api/proxy_status') == 'On')
					{
						$client = new SoapClient(Q::ini('custom_api/4PX_api_uri'), array('proxy_host' => Q::ini('custom_api/proxy_host'), 'proxy_port' => Q::ini('custom_api/proxy_port')));
					}
					else
					{
						$client = new SoapClient(Q::ini('custom_api/4PX_api_uri'));
					}
					$result = $client->CreateAndPreAlertOrderService($params);
				}
				catch(Exception $e)
				{
					echo "<h2>Exception Error!</h2>";
					echo $e->getMessage();
					continue;
				}
				catch(SoapFault $e)
				{
					echo "<h2>SoapFault Error!</h2>";
					echo $e->getMessage();
					continue;
				}
				if ($result->return->ack == 'Success')
				{
					QDB::getConn()->execute('update sales_order set tracking_number=\''. $result->return->trackingNumber . '\', lsp_number=\'' . $result->return->trackingNumber . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/4PX/value') . '\' where id=' . $so['id']);
				}
				else
				{
					$message .= $so['number'] . '：' . $result->return->errors->cnMessage . ';';
				}
			}
			else
			{
				$message .= $so['number'] . '：国家名称在系统找不到';
			}
		}
		return array('ack' => SUCCESS, 'message' => $message);
	}
	
	static function QTExpressSync($sales_order_ids, $order_type)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?)', $sales_order_ids)
		->joinLeft('sales_order_customer_info', 'fullname, street1, street2, city, state, zip, country, phone, email', 'sales_order_customer_info.sales_order_id=sales_order.id')
		->joinLeft('warehouse', 'code as warehouse_code', 'warehouse.id=sales_order.warehouse_id')
		->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
		->asArray()->getAll();
		$message = array();
		foreach ($sales_orders as $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'number, declared_value, declared_name_cn, declared_name_en, weight', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			$order = '';
			$weight = empty($item[0]['weight']) ? 10*$item[0]['quantity'] : $item[0]['weight'];
			$estimated_weight = (empty($so['estimated_weight']) || $so['estimated_weight'] == 0) ? $weight*$item[0]['quantity'] : $so['estimated_weight'];
			$estimated_weight = empty((int)$estimated_weight) ? 60 : (int)$estimated_weight;
			
			$order = '<?xml version="1.0" encoding="utf-8"?>
			<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
			<soap:Body>
			<SubmitOrder xmlns="http://diqisoft.com/">
			<order>
			<ExpressName>'.$order_type.'</ExpressName>
			<Weight>'.$estimated_weight.'</Weight>
			<Country>'.$so['country'].'</Country>
			<Province>'.$so['state'].'</Province>
			<City>'.$so['city'].'</City>
			<AddressLine1>'.($so['street1'] ? $so['street1'] : $so['street2']).'</AddressLine1>
			<AddressLine2>'.$so['street2'].'</AddressLine2>
			<Buyer>'.$so['fullname'].'</Buyer>
			<Telephone>'.$so['phone'].'</Telephone>
			<Email>'.$so['email'].'</Email>
			<PostCode>'.$so['zip'].'</PostCode>
			<OrderItems>';
			foreach ($item as $i)
			{
				$item_weight = (int)$i['weight'] ? (int)$i['weight'] : 10;
				$order .= '<OrderItemType>
				<DeclareName>'.$i['declared_name_en'].'</DeclareName>
				<DeclareValue>'.$i['declared_value'].'</DeclareValue>
				<Quantity>'.$i['quantity'].'</Quantity>
				<Weight>'.$item_weight.'</Weight>
				<SKU>'.$i['number'].'</SKU>
				</OrderItemType>';
			}
			$order .= '</OrderItems>
	        <Quantity>1</Quantity>
			<CustomOrderId>'.$so['number'].'</CustomOrderId>
			</order>
			<code>KSW</code>
			<token>C6B52C3F05424C7BA146061EE5DC7E76</token>
			</SubmitOrder>
		  	</soap:Body>
			</soap:Envelope>';
			$ch = curl_init('http://120.27.31.27:1680/api/shipping.asmx');
			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
			curl_setopt($ch, CURLOPT_POSTFIELDS, $order);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($ch, CURLOPT_HTTPHEADER, array(
				'Content-Type: text/xml; charset=utf-8',
				'Content-Length: ' . strlen($order))
			);
			$result = curl_exec($ch);
			if ($result)
			{
				$p = xml_parser_create();
				xml_parse_into_struct($p, $result, $vals, $index);
				xml_parser_free($p);
				$sync = false;
				foreach ($vals as $v)
				{
					if ($v['tag'] == 'ORDERID' && !empty($v['value']))
					{
						QDB::getConn()->execute('update sales_order set synchronous_flag =\'' . Q::ini('custom_flag/sales_order_synchronous_flag/QT/value') . '\', lsp_number=\''. $v['value'] . '\' where id=' . $so['id']);
						$sync = true;
					}
					if ($v['tag'] == 'TRACKINGNUMBER' && !empty($v['value']))
					{
						QDB::getConn()->execute('update sales_order set tracking_number=\''. $v['value'] . '\' where id=' . $so['id']);
					}
				}
				if (!$sync) $message[] = $so['number'] . '同步失败：' . $result;
			}
			else
			{
				$message[] = $so['number'] . '同步失败：' . $result;
			}
		}
		return array('ack' => $message ? FAILURE : SUCCESS, 'message' => implode("\n", $message));
	}
	
	static function BYExpressSync($sales_order_ids, $order_type, $post_type)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?)', $sales_order_ids)
			->joinLeft('sales_order_customer_info', 'fullname, street1, street2, city, state, zip, country, phone, email', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->joinLeft('warehouse', 'code as warehouse_code', 'warehouse.id=sales_order.warehouse_id')
			->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
			->asArray()->getAll();
		$message = $parcel = array();
		foreach ($sales_orders as $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'number, declared_value, declared_name_cn, declared_name_en, weight', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			$order = '';
			$weight = empty($item[0]['weight']) ? 10*$item[0]['quantity'] : $item[0]['weight'];
			$estimated_weight = (empty($so['estimated_weight']) || $so['estimated_weight'] == 0) ? $weight*$item[0]['quantity'] : $so['estimated_weight'];
			$delimiter = '||';
			$order .= $so['number'] . $delimiter;
			$order .= '自送' . $delimiter;
			$order .= $so['warehouse_code'] . $delimiter;
			$order .= Helper_BSS_Normal::getIniOne('by_order_type', 'code', $order_type, 'value') . $delimiter;
			$order .= $order_type . ($post_type == Q::ini('custom_flag/sync_post_type/register/value') ? ',挂号' : ',平邮') . $delimiter;
			$order .= $estimated_weight . $delimiter;
			$order .= 15 . $delimiter;
			$order .= 15 . $delimiter;
			$order .= 15 . $delimiter;
			$order .= $delimiter;
			$order .= $delimiter;
			$order .= $item[0]['number'] . $delimiter;
			$order .= $item[0]['declared_name_en'] . '|' . $item[0]['declared_name_cn'] . $delimiter;
			$order .= $item[0]['declared_value'] . $delimiter;
			$order .= $weight . $delimiter;
			$order .= $item[0]['quantity'] . $delimiter;
			$order .= $so['fullname'] . $delimiter;
			$order .= $so['street1'] . $delimiter;
			$order .= $so['street2'] . $delimiter;
			$order .= $so['city'] . $delimiter;
			$order .= $so['state'] . $delimiter;
			$order .= $so['zip'] . $delimiter;
			$order .= ($so['shipping_method'] == 2 ? $so['country_code'] : $so['country']) . $delimiter;
			$order .= $so['phone'] . $delimiter;
			$order .= $so['email'];
			try
			{
				$client = new SoapClient(Q::ini('custom_api/BY_api_uri'));
				$result = $client->OrderAdd(array('username' => Q::ini('custom_api/BY_api_uname'), 'pwd' => Q::ini('custom_api/BY_api_upasswd'), 'orderinfo' => $order, 'labelType' => 2, 'needDeclaration' => false));
			}
			catch (Exception $e)
			{
				echo "<h2>Exception Error!</h2>";
				echo $e->getMessage();
				exit;
			}
			catch (SoapFault $e)
			{
				echo "<h2>SoapFault Error!</h2>";
				echo $e->getMessage();
				exit;
			}
			$result = explode('||', $result->OrderAddResult);
			if ($result[0] == 'SUCCESS')
			{
				QDB::getConn()->execute('update sales_order set synchronous_flag =\'' . Q::ini('custom_flag/sales_order_synchronous_flag/BY/value') . '\' where id=' . $so['id']);
				if (!empty($result[1]) && $so['shipping_method'] == 2)
				{
					$tmp = explode(';', $result[1]);
					$tracking_number = explode(':', $tmp[1]);
					if (!empty($tracking_number[1]))
					{
						QDB::getConn()->execute('update sales_order set tracking_number =\'' . $tracking_number[1] . '\' where id=' . $so['id']);
					}
					else
					{
						$message[] = $so['number'] . '：EUB追踪号为空' . ';';
					}
				}
			}
			else
			{
				$message[] = $so['number'] . '：' . $result[1] . ';';
			}
		}
		return array('ack' => $message ? FAILURE : SUCCESS, 'message' => implode("\n", $message));
	}
	
	static function bpostExpressSync($sales_order_ids, $order_type)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			->joinLeft('sales_order_customer_info', 'fullname, street1, street2, zip, city, state, country, phone, email', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->asArray()->getAll();
		$message = '';
		foreach ($sales_orders as $key => $so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'number, declared_value, declared_name_cn, declared_name_en, weight', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			$product_list = array();
			$count_declared_value = 0;
			foreach ($item as $key => $i)
			{
				$count_declared_value += $i['declared_value'] * $i['quantity'];
				$product_list[$key] = array(
					'Sku' => $i['number'],
					'ChineseContentDescription' => $i['declared_name_cn'],
					'ItemContent' => $i['declared_name_en'],
					'ItemCount' => $i['quantity'],
					'Value' => $i['declared_value'],
					'Currency' => 'USD',
					'Weight' => (int)$i['weight'],
					'SkuInInvoice' => $i['number']
				);
			}
			if ($count_declared_value > 21.99)
			{
				$count_declared_value = 21.99;
				$count_product_declared_value = sprintf('%.2f', 21.99 / count($item));
				foreach ($item as $key => $i)
				{
					$product_list[$key]['Value'] = sprintf('%.2f', $count_product_declared_value / $i['quantity']);
				}
			}
			$data = array(
				'ContractId' => 1,
				'OrderNumber' => $so['number'],
				'RecipientName' => $so['fullname'],
				'RecipientStreet' => $so['street1'] . ' ' . $so['street2'],
				'RecipientZipCode' => $so['zip'],
				'RecipientCity' => $so['city'],
				'RecipientState' => $so['state'],
				'RecipientCountry' => strtoupper($so['country']),
				'PhoneNumber' => $so['phone'],
				'Email' => $so['email'],
				'Customs' => $product_list
			);
			$ch = curl_init();
			$timeout = 300;
			$service_uri = Q::ini('custom_api/Bpost_api_uri') . $order_type . 'Parcels';
			curl_setopt($ch, CURLOPT_URL, $service_uri);
			curl_setopt($ch, CURLOPT_POST, true);
			curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: basic ' . base64_encode(Q::ini('custom_api/Bpost_api_uname') . ':' . Q::ini('custom_api/Bpost_api_upasswd')), 'Content-Type: text/json', 'Charset=utf-8'));
			if (Q::ini('custom_api/proxy_status') == 'On')
			{
				curl_setopt(ch, CURLOPT_PROXY, Q::ini('custom_api/proxy_host') . ':' . Q::ini('custom_api/proxy_port'));
			}
			curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
			$response = json_decode(curl_exec($ch), true);
			curl_close($ch);
			if (isset($response['ProductBarcode']))
			{
				QDB::getConn()->execute('update sales_order set tracking_number=\''. $response['ProductBarcode'] . '\', lsp_number=\'' . $response['ProductBarcode'] . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/Bpost/value') . '\' where id=' . $so['id']);
			}
			else
			{
				$message .= $so['number'] . '：' . $response['model'] . ';';
			}
		}
		return array('ack' => SUCCESS, 'message' => $message);
	}
	
	static function BUBExpressSync($sales_order_ids, $order_type)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))->order('sales_order.sales_time asc')
			->joinLeft('sales_order_customer_info', 'fullname, street1, street2, zip, city, state, country, phone, email', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->asArray()->getAll();
		$message = '';
		foreach ($sales_orders as $key => $so)
		{
			$item = Sales_Order_Item::find('sales_order_item.sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'weight, declared_value, declared_name_cn, declared_name_en', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			$declared_value = 0;
			foreach ($item as $it)
			{
				$declared_value += $it['declared_value'];
			}
			$declared_value = ($declared_value > 20) ? 19.9 : $declared_value;
			$country = preg_replace(array('/^Russian Federation$/', '/^Netherlands$/', '/^Czech republic$/'), array('Russia', 'Netherland', 'Czech'), $so['country']);
			$data = array(
				'api_key' => Q::ini('custom_api/bub_api_key'),
				'from' => 'xu shao peng',
				'sender_province' => 'GuangDong',
				'sender_city' => 'GuangZhou',
				'sender_addres' => '广州市天河区骏景花园骏茵轩A3座404房',
				'sender_phone' => '13580349452',
				'to' => $so['fullname'],
				'recipient_country' => $country,
				'recipient_province' => $so['state'],
				'recipient_city' => $so['city'],
				'recipient_addres' => $so['street1'] . ' ' . $so['street2'],
				'recipient_postcode' => $so['zip'],
				'recipient_phone' => ($so['phone']) ? $so['phone'] : 0,
				'to_local' => $so['fullname'],
				'recipient_country_local' => $country,
				'recipient_province_local' => $so['state'],
				'recipient_city_local' => $so['city'],
				'recipient_addres_local' => $so['street1'] . ' ' . $so['street2'],
				'type_no' => 4,
				'from_country' => 'China',
				'content' => $item[0]['declared_name_en'],
				'num' => $so['product_quantity'],
				'weight' => ($so['weight']/1000 <= 2) ? ($so['weight'] / 1000) : 1.99,
				'single_price' => sprintf('%.2f', $declared_value / $so['product_quantity']),
				'user_desc' => $so['number'],
				'trande_no' => '',
				'trade_amount' => $so['amount'],
				'otype' => $order_type
			);
			$timeout = 300;
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, Q::ini('custom_api/bub_api_uri'));
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
			curl_setopt($ch, CURLOPT_POST, true);
			if (Q::ini('custom_api/proxy_status') == 'On')
			{
				curl_setopt($ch, CURLOPT_PROXY, Q::ini('custom_api/proxy_host') . ':' . Q::ini('custom_api/proxy_port'));
			}
			curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
			$response = curl_exec($ch);
			curl_close($ch);
			$response = simplexml_load_string($response);
			if (isset($response->status) && $response->status == 0)
			{
				QDB::getConn()->execute('update sales_order set tracking_number=\''. (string)$response->barcode . '\', lsp_number=\'' . (string)$response->barcode . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/BUB/value') . '\' where id=' . $so['id']);
			}
			else
			{
				$message .= $so['number'] . '：' . $response->error_message . ';';
			}
		}
		return array('ack' => SUCCESS, 'message' => $message);
	}
	
	static function SFExpressSync($sales_order_ids, $order_type)
	{
		$sales_order = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			->joinLeft('sales_order_customer_info', 'fullname, phone, email, street1, street2, city, zip, state, country', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
			->asArray()->getAll();
		$message = '';
		foreach ($sales_order as $so)
		{
			$cargo_total_weight = sprintf('%.2f', ($so['estimated_weight']/1000));
			$address = $so['street2'] . ' ' . $so['street1'];
			$xml = '<Request service="OrderService" lang="zh-CN">';
			$xml .= '<Head>' . Q::ini('custom_api/SF_api_userid') . '</Head>';
			$xml .= '<Body>';
			$xml .= '<Order orderid="' . $so['number'] . '" express_type="' . $order_type . '" d_contact="' . $so['fullname'] . '" d_mobile="' . $so['phone'] . '" d_address="' . $address . '" d_country="' . $so['country_code']. '" cargo_total_weight="' . $cargo_total_weight . '" d_province="' . $so['state'] . '" d_city="' . $so['city'] . '" returnsign="Y" operate_flag="1">';
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])
					->joinLeft('product_basic', 'declared_value, declared_name_cn, declared_name_en', 'product_basic.id=sales_order_item.product_basic_id')
					->asArray()->getAll();
			foreach ($item as $k => $i)
			{
				$amount = sprintf('%.2f', $i['declared_value']);
				$xml .= "<Cargo name='{$i['declared_name_cn']}' ename='{$i['declared_name_en']}' count='{$i['quantity']}' amount='{$amount}'>";
				$xml .= '</Cargo>';
			}
			$xml .= '</Order>';
			$xml .= '</Body>';
			$xml .= '</Request>';
			$key = base64_encode(strtoupper(md5($xml . Q::ini('custom_api/SF_api_appkey'))));
			$soap = new SoapClient(Q::ini('custom_api/SF_api_uri'));
			$result = $soap->sfexpressService($xml, $key);
			$array = json_decode(json_encode(simplexml_load_string($result)), true);
			if ($array['Head'] != 'OK')
			{
				preg_match("#<ERROR code=\"(\d{4})\">#", $result, $code);
				$message .= $so['number'] . $array['ERROR'] . "错误代码(" . $code[1] . ")\n";
			}
			else
			{
				QDB::getConn()->execute('update sales_order set tracking_number=\''. $array['Body']['OrderResponse']['@attributes']['agent_mailno'] . '\', lsp_number=\'' . $array['Body']['OrderResponse']['@attributes']['mailno'] . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/SF/value') . '\' where id=' . $so['id']);
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => $message);
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	static function AEExpressSync($sales_order_ids, $order_type)
	{
		set_time_limit(0);
		$sales_orders = Sales_Order::find('sales_order.id in (?) and (sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=? or sales_order.handle_status=?)', $sales_order_ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'), Q::ini('custom_flag/sales_order_handle_status/printed/value'), Q::ini('custom_flag/sales_order_handle_status/printed_address/value'), Q::ini('custom_flag/sales_order_handle_status/weighed/value'))->order('sales_order.sales_time asc')
			->joinLeft('sales_order_customer_info', 'fullname, street1, street2, zip, city, state, country, phone, email', 'sales_order_customer_info.sales_order_id=sales_order.id')
			->joinLeft('country', 'country.code as country_code', 'country.en_name = sales_order_customer_info.country')
			->asArray()->getAll();
		$message = '';
		foreach ($sales_orders as $key => $so)
		{
			$item = Sales_Order_Item::find('sales_order_item.sales_order_id=?', $so['id'])
				->joinLeft('product_basic', 'number, weight, declared_value, declared_name_cn, declared_name_en', 'product_basic.id=sales_order_item.product_basic_id')
				->asArray()->getAll();
			$api = Shop_API_AliExpress::getAPIByShopId($so['shop_id']);
			if ($api['ack'] == SUCCESS)
			{
				$uri = Q::ini('custom_api/aliexpress_uri') . 'api.createWarehouseOrder/' . $api['key'];
				$addressDTOs = $declareProductDTOs = array();
				$addressDTOs['receiver'] = array(
					'city' => $so['city'],
					'country' => $so['country_code'] == 'GB' ? 'UK' : $so['country_code'],
					'name' => $so['fullname'],
					'postcode' => $so['zip'],
					'email'=>$so['email'],
					'phone' => $so['phone'],
					'province' => $so['state'],
					'streetAddress' => $so['street1'] . ' ' . $so['street2']
				);
				$addressDTOs['sender'] = array(
					'city' => 'GuangZhou',
					'country' => 'CN',
					'county' => 'TianHe',
					'name' => 'HuangJianWei',
					'phone' => '13613019361',
					'postcode' => '510000',
					'province' => 'GuangDong',
					'streetAddress' => 'YunXiDong'
				);
				$addressDTOs = json_encode($addressDTOs, JSON_UNESCAPED_UNICODE);
				foreach ($item as $i)
				{
					$declareProductDTOs[] = array(
					'productId' => $i['shop_item_id'],
					'categoryCnDesc' => $i['declared_name_cn'],
					'categoryEnDesc' => $i['declared_name_en'],
					'productNum' => $i['quantity'],
					'productDeclareAmount' => $i['declared_value'],
					'productWeight' => sprintf('%.3f', ($i['weight']/1000)),
					'isContainsBattery' => 0,//是否包含锂电池
					'scItemId' => $i['number']
					); 
				}
				$declareProductDTOs = json_encode($declareProductDTOs, JSON_UNESCAPED_UNICODE);
				$param = array(
					'access_token' => $api['access_token'],
					'tradeOrderId' => $so['shop_order_number'],
					'tradeOrderFrom' => 'ESCROW',
					'domesticLogisticsCompanyId' => '-1',
					'domesticLogisticsCompany' => '顺丰',
					'domesticTrackingNo' => $so['shop_order_number'],
					'addressDTOs' => $addressDTOs,
					'warehouseCarrierService' => $order_type,
					'declareProductDTOs' => $declareProductDTOs,
				);
				if ($so['synchronous_flag'] == Q::ini('custom_flag/sales_order_synchronous_flag/Ali/value'))
				{
					$message .= $so['number'] . "重复同步，请检查速卖通后台数据是否重复\n";
				}
				$result = Helper_BSS_API::AliExpressAPICall($uri, $param, false);
				if (isset($result['success']) && $result['success'] == 1)
				{
					QDB::getConn()->execute('update sales_order set synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/Ali/value') . '\', lsp_number=\'' . $result['result']['warehouseOrderId'] . '\' where id=' . $so['id']);
					sleep(15);
					$getresult = Sales_Order::GetAEOrderTrackingNum($so['id']);
					$message .= $getresult['message'];
				}
				elseif (isset($result['result']['errorDesc']))
				{
					$message .= $so['number'] . '同步失败,原因：' . $result['result']['errorDesc'] .  "\n";
				}
				elseif (isset($result['error_message']))
				{
					$message .= $so['number'] . '同步失败,原因：' . $result['error_message'] .  "\n";
				}
				elseif (isset($result['message']))
				{
					$message .= $so['number'] . '同步失败,原因：' . $result['message'] .  "\n";
				}
				else
				{
					$message .= $so['number'] . '同步失败' . "\n";
				}
			}
			else
			{
				$message .= $so['number'] . '授权失败' . "\n";
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => $message);
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	static function GetAEOrderTrackingNum($sales_order_id)
	{
		$sales_order = Sales_Order::find('sales_order.id=?', $sales_order_id)->asArray()->getOne();
		$api = Shop_API_AliExpress::getAPIByShopId($sales_order['shop_id']);
		if ($api['ack'] == SUCCESS)
		{
			$uri = Q::ini('custom_api/aliexpress_uri') . 'api.getOnlineLogisticsInfo/' . $api['key'];
			$param = array(
				'access_token' => $api['access_token'],
				'orderId' => $sales_order['shop_order_number']
                        );
			$result = Helper_BSS_API::AliExpressAPICall($uri, $param, false);
			if (isset($result['success']) && $result['success'] == 1)
			{
				QDB::getConn()->execute('update sales_order set tracking_number=\''. $result['result'][0]['internationallogisticsId'] . '\' where id=' . $sales_order['id']);
				return array('ack' => SUCCESS, 'message' => $sales_order['number'] . '获取成功');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . '获取失败');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $sales_order['number'] . '授权失败');
		}
	}
	
	static function importEbayOrderByAPI($shop_id, $mod_time_from, $mod_time_to, $orderstatus='Completed')
	{ 	
		$token = Shop_API_Ebay::find('shop_id=?', $shop_id)->asArray()->getOne();
		if ($token)
		{
			$ps = 100;
			$cp = 0;
			$total_entries = 1;
			$header = array(
				'X-EBAY-API-COMPATIBILITY-LEVEL:' . Q::ini('custom_api/X-EBAY-API-COMPATIBILITY-LEVEL'),
				'X-EBAY-API-DEV-NAME:' . Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
				'X-EBAY-API-APP-NAME:' . Q::ini('custom_api/X-EBAY-API-APP-NAME'),
				'X-EBAY-API-CERT-NAME:' . Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
				'X-EBAY-API-SITEID:0',
				'X-EBAY-API-CALL-NAME:GetOrders'
			);
			$message = '';
			while ($ps*$cp < $total_entries)
			{
				$cp++;
				$xml = '<?xml version="1.0" encoding="utf-8"?>';
				$xml .= '<GetOrdersRequest xmlns="urn:ebay:apis:eBLBaseComponents">';
				$xml .= '<RequesterCredentials>';
				$xml .= '<eBayAuthToken>' . $token['token'] . '</eBayAuthToken>';
				$xml .= '</RequesterCredentials>';
// 				$xml .= '<CreateTimeFrom>' . $mod_time_from . '</CreateTimeFrom>';
// 				$xml .= '<CreateTimeTo>' . $mod_time_to . '</CreateTimeTo>';
				$xml .= '<ModTimeFrom>' . $mod_time_from . '</ModTimeFrom>';
				$xml .= '<ModTimeTo>' . $mod_time_to . '</ModTimeTo>';
				$xml .= '<DetailLevel>ReturnAll</DetailLevel>';
				$xml .= '<IncludeFinalValueFee>True</IncludeFinalValueFee>';
				$xml .= '<OrderStatus>' . $orderstatus . '</OrderStatus>';
				$xml .= '<Pagination>';
				$xml .= '<EntriesPerPage>' . $ps . '</EntriesPerPage>';
				$xml .= '<PageNumber>' . $cp . '</PageNumber>';
				$xml .= '</Pagination>';
				$xml .= '<OutputSelector>OrderArray.Order.BuyerUserID</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.ShippingAddress</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.AmountPaid</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.PaidTime</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.Buyer.Email</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.Item.ItemID</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.Item.SKU</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.QuantityPurchased</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.TransactionID</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.TransactionPrice</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.Variation.SKU</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.CreatedTime</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.CheckoutStatus.eBayPaymentStatus</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.ShippingDetails.SellingManagerSalesRecordNumber</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.ShippingServiceSelected.ShippingServiceCost</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.BuyerCheckoutMessage</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.ExternalTransaction.ExternalTransactionID</OutputSelector>';
				$xml .= '<OutputSelector>OrderArray.Order.TransactionArray.Transaction.FinalValueFee</OutputSelector>';
				$xml .= '<OutputSelector>PaginationResult</OutputSelector>';
				$xml .= '</GetOrdersRequest>';
				$result = Helper_BSS_API::ebayAPICall(Q::ini('custom_api/ebay_ws_uri'), $header, $xml, 'GetOrders', $shop_id . '-' . $cp);
				if ($result['ack'] == SUCCESS)
				{
					$response = simplexml_load_string($result['data']);
					if ($response)
					{
						$total_entries = (string)$response->PaginationResult[0]->TotalNumberOfEntries[0];
						$current_page_order = Helper_BSS_XML::ebayXMLToOrderArray($shop_id, $response);
						$import_result = Sales_Order::import($current_page_order);
						if ($import_result['ack'] == PARTIAL_FAILURE)
						{
							$message .= $import_result['message'] . "\n";
						}
					}
				}
				else
				{
					$message .= $result['message'] . "\n";
				}
			} 
			if ($message)
			{
				return array('ack' => PARTIAL_FAILURE, 'message' => $message);
			}
			else
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
		}
	}
	
	static function ebayOrderMarkShipped($ids)
	{
		$message = '';
		foreach ($ids as $id)
		{
			$header = array(
				'X-EBAY-API-COMPATIBILITY-LEVEL:' . Q::ini('custom_api/X-EBAY-API-COMPATIBILITY-LEVEL'),
				'X-EBAY-API-DEV-NAME:' . Q::ini('custom_api/X-EBAY-API-DEV-NAME'),
				'X-EBAY-API-APP-NAME:' . Q::ini('custom_api/X-EBAY-API-APP-NAME'),
				'X-EBAY-API-CERT-NAME:' . Q::ini('custom_api/X-EBAY-API-CERT-NAME'),
				'X-EBAY-API-SITEID:0',
				'X-EBAY-API-CALL-NAME:CompleteSale'
			);
			$judge_result = Sales_Order::judgeEbayOrderMarkShipped($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				$order = Sales_Order::find('sales_order.id=?', $id)
					->joinLeft('shipping_method', 'shipping_carrier', 'shipping_method.id=sales_order.shipping_method')
					->asArray()->getOne();
				$token = Shop_API_Ebay::find('shop_id=?', $order['shop_id'])->asArray()->getOne();
				$xml = '<?xml version="1.0" encoding="utf-8"?>';
				$xml .= '<CompleteSaleRequest xmlns="urn:ebay:apis:eBLBaseComponents">';
				$xml .= '<RequesterCredentials>';
				$xml .= '<eBayAuthToken>' . $token['token'] . '</eBayAuthToken>';
				$xml .= '</RequesterCredentials>';
				$xml .= '<Shipped>true</Shipped>';
				$xml .= '<Shipment>';
				$xml .= '<ShipmentTrackingDetails>';
				$xml .= '<ShipmentTrackingNumber>' . $order['tracking_number'] . '</ShipmentTrackingNumber>';
				$xml .= '<ShippingCarrierUsed>' . $order['shipping_carrier'] . '</ShippingCarrierUsed>';
				$xml .= '</ShipmentTrackingDetails>';
				$xml .= '</Shipment>';
				$xml_body = $xml;
				$order_item = Sales_Order_Item::find('sales_order_id=?', $id)->asArray()->getAll();
				foreach ($order_item as $oi)
				{
					if ($oi['shop_item_id'] && $oi['shop_transaction_id'])
					{
						$xml_body = $xml;
						$xml_body .= '<ItemID>' . $oi['shop_item_id'] . '</ItemID>';
						$xml_body .= '<TransactionID>' . $oi['shop_transaction_id'] . '</TransactionID>';
						$xml_body .= '<Shipped>true</Shipped>';
						$xml_body .= '</CompleteSaleRequest>';
						$result = Helper_BSS_API::ebayAPICall(Q::ini('custom_api/ebay_ws_uri'), $header, $xml_body, 'ComplteSale', '', true);
						$array = json_decode(json_encode(simplexml_load_string($result['data'])), true);
						if ($array['Ack'] == 'Failure')
						{
							$message .= $order['number'] . $array['Errors']['ShortMessage'] . ',ErrorCode:' . $array['Errors']['ErrorCode'] . "\n";
						}
					}
				}
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => $message);
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	static function judgeEbayOrderMarkShipped($sales_order_id)
	{
		$order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($order)
		{
			if ($order['shipping_status'] == Q::ini('custom_flag/sales_order_shipping_status/shipped/value') && $order['mark_shipped_flag'] == Q::ini('custom_flag/sales_order_mark_shipped_flag/unmarked/value'))
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $order['number'] . ': order has already marked');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $sales_order_id . ': order is not exists');
		}
	}
	
	static function zencartOrderMarkShipped($ids)
	{
		foreach ($ids as $id)
		{
			$judge_result = Sales_Order::judgeZencartOrderMarkShipped($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				$order = Sales_Order::find('id=?', $id)->asArray()->getOne();
				$data[] = array(
					'shop_order_number' => $order['shop_order_number'],
					'status' => '3',
					'email' => $judge_result['email']
				);
			}
			else
			{
				return array('ack' => $judge_result['ack'], 'message' => $judge_result['message']);
			}
		}
		$params['orderstatus'] = base64_encode(serialize($data));
		$result = Helper_BSS_API::PushZencartOrderTrackingNumberByAPI($order['shop_id'], $params);
		$message = '';
		foreach ($result as $r)
		{
			if ($r['ack'] == 'success')
			{
				QDB::getConn()->execute('update sales_order set mark_shipped_flag=' . Q::ini('custom_flag/sales_order_mark_shipped_flag/marked/value') . " where shop_order_number='{$r['shop_order_number']}'");
			}
			else
			{
				$message .= $r['shop_order_number'] . ', ';
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => 'wrong shop order number：' . $message);
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	static function judgeZencartOrderMarkShipped($sales_order_id)
	{
		$order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($order)
		{
			$tracking_number = 'None';
			$tracking_website = 'None';
			if ($order['tracking_number'])
			{
				$tracking_number = $order['tracking_number'];
				$tracking_website = 'http://www.17track.net/IndexEn.html';
			}
			$sales_time = strtotime($order['sales_time']);
			$shipped_time = strtotime($order['shipped_time']);
			$date = date('F, j', (($shipped_time - $sales_time)/86400 > 3) ? ($sales_time+86400*3) : $sales_time);
			$shop = Shop::find('id=?', $order['shop_id'])->asArray()->getOne();
			if ($order['shipping_status'] == Q::ini('custom_flag/sales_order_shipping_status/shipped/value') && $order['mark_shipped_flag'] == Q::ini('custom_flag/sales_order_mark_shipped_flag/unmarked/value'))
			{
				switch ($shop['name'])
				{
					case 'iwowcase.com':
						$email = "Your order has been shipped on {$date} from our China warehouse.
Tracking No. : {$tracking_number}
Tracking Website: {$tracking_website}
As the customs screening is quite strict recently for this very season. We advise you to wait for few days more or check the parcel at your local post office if don’t receive it at estimated time.
Any questions please feel free to contact us at www.iwowcase.com , customer’s satisfaction is our top value!

Delivery schedule for your reference:
Super Saver Shipping: Without tracking number, delivery time takes 10-25 Working days
Registered Air Mail: With tracking number, delivery time takes 10-25 Working days
EMS: With tracking number, delivery time takes 4-7 Working days
***Please note that all the packages will be delayed a bit for rush reason. Please allow at least 40 days for super saver and registered airmail, 10 days for EMS.Sorry for any inconvenience.";
						return array('ack' => SUCCESS, 'message' => '', 'email' => $email);
					case 'glwf.com':
						$email = "Your order has been shipped on {$date} from our China warehouse.
Tracking No. : {$tracking_number}
Tracking Website: {$tracking_website}
As the customs screening is quite strict recently for this very season. We advise you to wait for few days more or check the parcel at your local post office if don’t receive it at estimated time.
Any questions please feel free to contact us at www.glwf.com , customer’s satisfaction is our top value!

Delivery schedule for your reference:
Super Saver Shipping: Without tracking number, delivery time takes 10-25 Working days
Registered Air Mail: With tracking number, delivery time takes 10-25 Working days
EMS: With tracking number, delivery time takes 4-7 Working days
***Please note that all the packages will be delayed a bit for rush reason. Please allow at least 40 days for super saver and registered airmail, 10 days for EMS.Sorry for any inconvenience.";
						return array('ack' => SUCCESS, 'message' => '', 'email' => $email);
					case 'yehair.com':
						$email = "Your order has been shipped on {$date} from our China warehouse.
Tracking No. : {$tracking_number}
Tracking Website: {$tracking_website}
As the customs screening is quite strict recently for this very season. We advise you to wait for few days more or check the parcel at your local post office if don’t receive it at estimated time.
Any questions please feel free to contact service@yehair.com, customer’s satisfaction is our top value!

Delivery schedule for your reference:
Standard International Shipping: With tracking number, delivery time takes 10-25 Working days
EMS Express Shipping: With tracking number, delivery time takes 7-15 Working days
DHL Express Shipping: With tracking number, delivery time takes 3-5 Working days
";
						return array('ack' => SUCCESS, 'message' => '', 'email' => $email);
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $order['number'] . ': order status error(shipping_status=' . $order['shipping_status'] . ', mark_shipped_flag=' . $order['shipping_status'] . ')!');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'order is not exists');
		}
	}
	
	static function amazonOrderMarkShipped($ids, $type)
	{
		$judge_result = Sales_Order::judgeAmazonOrderMarkShipped($ids, $type);
		if ($judge_result['ack'] == SUCCESS)
		{
			$amazon_shop = Shop_API_Amazon::find('shop_api_amazon.shop_id=shop.id')
				->joinLeft('shop', 'platform as shop_platform', 'shop.name=\''.$judge_result['type'].'\'')
				->asArray()->getOne();
			$xml = '<?xml version="1.0" encoding="UTF-8"?>';
			$xml .= '<AmazonEnvelope xsi:noNamespaceSchemaLocation="amzn-envelope.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
			$xml .= '<Header>';
			$xml .= '<DocumentVersion>1.01</DocumentVersion>';
			$xml .= '<MerchantIdentifier>' . $amazon_shop['merchant_id'] . '</MerchantIdentifier>';
			$xml .= '</Header>';
			$xml .= '<MessageType>OrderFulfillment</MessageType>';
			$k = 1;
			foreach ($ids as $id)
			{
				$order = Sales_Order::find('sales_order.id=?', $id)
					->joinLeft('shipping_method', 'shipping_carrier', 'shipping_method.id=sales_order.shipping_method')
					->asArray()->getOne();
				if ($order['id'])
				{
					$xml .= '<Message>';
					$xml .= '<MessageID>' . $k . '</MessageID>';
					$xml .= '<OperationType>Update</OperationType>';
					$xml .= '<OrderFulfillment>';
					$xml .= '<AmazonOrderID>' . $order['shop_order_number'] . '</AmazonOrderID>';
					$xml .= '<FulfillmentDate>' . date('c', CURRENT_TIMESTAMP) . '</FulfillmentDate>';
					$xml .= '<FulfillmentData>';
					$xml .= '<CarrierName>' . $order['shipping_carrier'] . '</CarrierName>';
					$xml .= '<ShippingMethod>Standard</ShippingMethod>';
					$xml .= '<ShipperTrackingNumber>' . $order['tracking_number'] . '</ShipperTrackingNumber>';
					$xml .= '</FulfillmentData>';
					$xml .= '</OrderFulfillment>';
					$xml .= '</Message>';
					$combine_order = Sales_Order_Combine_Mapping::find('sales_order_combine_mapping.original_sales_order_id=?', $order['id'])
						->joinLeft('sales_order', 'shop_order_number', 'sales_order.id=sales_order_combine_mapping.combined_sales_order_id')
						->asArray()->getAll();
					if (! empty($combine_order))
					{
						foreach ($combine_order as $co)
						{
							$k = $k + 1;
							$xml .= '<Message>';
							$xml .= '<MessageID>' . $k . '</MessageID>';
							$xml .= '<OperationType>Update</OperationType>';
							$xml .= '<OrderFulfillment>';
							$xml .= '<AmazonOrderID>' . $co['shop_order_number'] . '</AmazonOrderID>';
							$xml .= '<FulfillmentDate>' . date('c', CURRENT_TIMESTAMP) . '</FulfillmentDate>';
							$xml .= '<FulfillmentData>';
							$xml .= '<CarrierName>' . $order['shipping_carrier'] . '</CarrierName>';
							$xml .= '<ShippingMethod>Standard</ShippingMethod>';
							$xml .= '<ShipperTrackingNumber>' . $order['tracking_number'] . '</ShipperTrackingNumber>';
							$xml .= '</FulfillmentData>';
							$xml .= '</OrderFulfillment>';
							$xml .= '</Message>';
						}
					}
					$k++;
				}
			}
			$xml .= '</AmazonEnvelope>';
			$result = Helper_BSS_API::submitFeedToAmazon($amazon_shop['shop_id'], $xml, '_POST_ORDER_FULFILLMENT_DATA_');
			if ($result['ack'] == SUCCESS)
			{
				QDB::getConn()->execute('update sales_order set mark_shipped_flag=' . Q::ini('custom_flag/sales_order_mark_shipped_flag/marked/value') . ' where id in (' . implode(',', $ids) . ')');
			}
			exit;
		}
		else
		{
			return array('ack'=> $judge_result['ack'], 'message' => $judge_result['message']);
		}
	}
	
	static function judgeAmazonOrderMarkShipped($sales_order_ids, $type)
	{
		$sales_orders = Sales_Order::find('sales_order.id in (?)', $sales_order_ids)
			->joinLeft('shop', 'name as shop_name, platform as shop_platform', 'shop.id=sales_order.shop_id')
			->asArray()->getAll();
		$shop_name = $sales_orders[0]['shop_name'];
		foreach ($sales_orders as $so)
		{
			if ($so['shop_platform'] == $type)
			{
				if ($so['shop_name'] == $shop_name)
				{
					if ($so['mark_shipped_flag'] == Q::ini('custom_flag/sales_order_mark_shipped_flag/marked/value'))
					{
						return array('ack' => FAILURE, 'message' => '订单：' . $so['number'] . '同步状态错误！');
					}
				}
				else
				{
					return array('ack' => FAILURE, 'message' => '订单：' . $so['number'] . '店铺错误，一次同步只能操作一个店铺！');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => '订单：' . $so['number'] . '平台错误！');
			}
		}
		return array('ack' => SUCCESS, 'type' => $shop_name, 'message' => '');
	}
	
	static function exportShipmentFileAmazon($order_ids)
	{
		$text = "order-id\torder-item-id\tquantity\tship-date\tcarrier-code\tcarrier-name\ttracking-numer\tship-method\r\n";
		foreach ($order_ids as $id)
		{
			$order = Sales_Order::find('sales_order.id=?', $id)
				->joinLeft('shipping_method', 'carrier_code,shipping_carrier', 'shipping_method.id=sales_order.shipping_method')
				->asArray()->getOne();
			if ($order)
			{
				QDB::getConn()->execute('update sales_order set mark_shipped_flag=' . Q::ini('custom_flag/sales_order_mark_shipped_flag/marked/value') . ' where id=' . $order['id']);
				$item = Sales_Order_Item::find('sales_order_id=?', $id)->asArray()->getAll();
				foreach ($item as $i)
				{
					$text .= $order['shop_order_number'] . "\t" . $i['shop_item_id'] . "\t" . $i['quantity'] . "\t" . date('Y-m-d', CURRENT_TIMESTAMP) . "\t" . $order['carrier_code'] . "\t" . $order['shipping_carrier'] . "\t" . $order['tracking_number'] . "\t\r\n";
				}
			}
		}
		return $text;
	}
	
	static function getWishOrderByAPI($shop_id, $date)
	{
		$token = Shop_API_Wish::find('shop_id=?', $shop_id)->asArray()->getOne();
		if ($token)
		{
			$data = Shop_API_Wish::getOrderByAPI($token['access_token'], $date);
			if ($data) return array('ack' => SUCCESS, 'message' => '', 'data' => $data);
			return array('ack' => FAILURE, 'message' => 'empty order data');
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'token error');
		}
	}
	
	static function pushTracking($order_ids)
	{
		$judge = self::judgePushTracking($order_ids);
		if ($judge['ack'] == SUCCESS)
		{
			$push = array();
			foreach ($order_ids as $oi)
			{
				$order = self::find('id=?', $oi)->asArray()->getOne();
				$tracking = array('tracking_number' => $order['tracking_number'], 'shipping_method' => $order['shipping_method']);
				$push[] = $tracking;
			}
			$service_uri = 'http://tracking.xftl.com/tracking-add.php';
			$secret_key = 'VP3XQpDsuN7LcVKhdK4MXU3fWRGQEcV7';
			$authenticate = md5(CURRENT_TIMESTAMP . $secret_key);
			$post = array(
				'time' => CURRENT_TIMESTAMP,
				'authenticate' => $authenticate,
				'tracking' => json_encode($push)
			);
			$connection = curl_init();
			curl_setopt($connection, CURLOPT_URL, $service_uri);
			curl_setopt($connection, CURLOPT_POST, true);
			curl_setopt($connection, CURLOPT_POSTFIELDS, $post);
			curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1);
			$response = curl_exec($connection);
			$result = json_decode($response, true);
			if ($result['ack'] == SUCCESS)
			{
				QDB::getConn()->execute('update sales_order set mark_shipped_flag=' . Q::ini('custom_flag/sales_order_mark_shipped_flag/marked/value') . ' where id in (' . implode(',', $order_ids) . ')');
			}
			return array('ack' => $result['ack'], 'message' => $result['message']);
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $judge['message']);
		}
	}
	
	static function judgePushTracking($order_ids)
	{
		$ack = true;
		$message = '';
		foreach ($order_ids as $oi)
		{
			$order = Sales_Order::find('id=?', $oi)->asArray()->getOne();
			if ($order['handle_status'] != Q::ini('custom_flag/sales_order_handle_status/shipped/value') || empty($order['tracking_number']))
			{
				$ack = false;
				$message .= $order['number'] . 'tracking number is empty';
			}
			elseif(! ($order['shipping_method'] == Shipping_Method::getShippingMethodByCode('GZ_N_DE_Package') || $order['shipping_method'] == Shipping_Method::getShippingMethodByCode('GZ_N_EU_Line')))
			{
				$ack = false;
				$message .= $order['number'] . 'shipping method is error';
			}
		}
		if ($ack)
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $message . '');
		}
	}
	
	/**
	 * 订单称重&计算运费
	 * @param $number
	 * @param $shipping_method
	 * @param $weight
	 * @param $pack_user_id
	 * @return array
	 */
	static function weigh($number, $shipping_method, $weight, $pack_user_id)
	{
		$ack = FAILURE;
		$message = $order_number = $estimated_weight = $shipping_fee = $postage_currency_symbol = '';
		$order = Sales_Order::find('number=? or tracking_number=? or lsp_number=?', $number, $number, $number)->asArray()->getAll();
		if (count($order))
		{
			if (count($order) == 1)
			{
				$order = $order[0];
				if (in_array($order['shipping_method'], explode(',', $shipping_method)))
				{
					if ($order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/printed_address/value') || $order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
					{
						if ($order['tips_flag'])
						{
							$message = '订单异常：' . Helper_BSS_Normal::getIniOne('sales_order_tips_flag', 'value', $order['tips_flag'], 'name');
							$order_number = $order['number'];
						}
						else
						{
							$formula = Shipping_Method::find('id=?', $order['shipping_method'])->asArray()->getOne();
							if ($formula && $formula['formula'])
							{
								$order_detail_info = Sales_Order_Customer_Info::find('sales_order_customer_info.sales_order_id=?', $order['id'])
									->joinLeft('country', 'code', 'country.en_name=sales_order_customer_info.country')
									->asArray()->getOne();
								$variable = array('weight' => $weight, 'country_code' => $order_detail_info['code']);
								eval($formula['formula']);
								$shipping_fee = ceil($formula_result['postage'] * 100) / 100;
							}
							else
							{
								$shipping_fee = 0;
								$formula_result = array('ack' => SUCCESS, 'message' => '', 'postage_currency_code' => 'CNY');
							}
							if ($formula_result['ack'] == SUCCESS)
							{
								$currency = Currency::find('code=?', $formula_result['postage_currency_code'])->asArray()->getOne();
								QDB::getConn()->execute('update sales_order set weight='.$weight.', postage_currency_id='. $currency['id'] . ', postage_currency_rate=' . $currency['rate'] . ', postage=' . $shipping_fee . ', handle_status=' . Q::ini('custom_flag/sales_order_handle_status/weighed/value') . ',weigh_user_id=' . CURRENT_USER_ID . ',weigh_time=\'' . CURRENT_DATETIME . '\', pack_user_id=' . $pack_user_id . ' where id=' . $order['id']);
								$ack = SUCCESS;
								$postage_currency_symbol = $currency['symbol'];
								$order_number = $order['number'];
								$estimated_weight = $order['estimated_weight'];
								if ((int)$estimated_weight && abs(1 - $weight/$estimated_weight) > 0.3)
								{
									$ack = WARNING;
									$message = '实际跟估算重量超30%';
								}
							}
							else
							{
								$order_number = $order['number'];
								$message = $formula_result['message'];
							}
						}
					}
					else
					{
						$message = '订单状态错误';
						$order_number = $order['number'];
					}
				}
				else
				{
					$message = '订单邮寄方式错误';
					$order_number = $order['number'];
				}
			}
			else
			{
				$message = '多张订单：';
				foreach ($order as $o)
				{
					$message .= $o['number'] . ',';
				}
			}
		}
		else
		{
			$message = '没有找到订单';
		}
		return	array('ack' => $ack, 'message' => $message, 'order_number' => $order_number, 'weight' => $weight, 'estimated_weight' => $estimated_weight, 'shipping_fee' => $shipping_fee, 'postage_currency_symbol' => $postage_currency_symbol);
	}
	
	/**
	 * FBA订单出库
	 * @param $sales_order_ids
	 */
	static function outFBA($sales_order_ids)
	{
		foreach ($sales_order_ids as $id)
		{
			$judge = Sales_Order::judgeOutFBA($id);
			if ($judge['ack'] == SUCCESS)
			{
				$sales_order = Sales_Order::find('id=?', $id)->getOne();
				$warehouse_id = $sales_order['warehouse_id'];
				$currency_id = $sales_order['currency_id'];
				$currency_rate = $sales_order['currency_rate'];
				$sales_order->handle_status = Q::ini('custom_flag/sales_order_handle_status/shipped/value');
				$sales_order->shipped_user_id = CURRENT_USER_ID;
				$sales_order->shipped_time = CURRENT_DATETIME;
				$sales_order->shipping_status = Q::ini('custom_flag/sales_order_shipping_status/shipped/value');
				$sales_order->save();
				$item = Sales_Order_Item::find('sales_order_id=?', $id)->asArray()->getAll();
				foreach ($item as $i)
				{
					$cost_amount_result = Inventory_Log::getCostAmountByFIFO($i['product_basic_id'], $warehouse_id, $i['quantity']);
					$cost_price = $cost_amount_result['cost_amount'] / $i['quantity'];
					$log = new Inventory_Log();
					$log->product_basic_id = $i['product_basic_id'];
					$log->warehouse_id = $warehouse_id;
					$log->type = Q::ini('custom_flag/inventory_log_type/sales/value');
					$log->relate_table_id = $i['id'];
					$log->init_quantity = 0;
					$log->in_quantity = 0;
					$log->out_quantity = $i['quantity'];
					$log->cost_price = $cost_price;
					$log->sales_price = $i['sales_price'];
					$log->cost_amount = $cost_amount_result['cost_amount'];
					$log->sales_amount = $i['sales_price'] * $i['quantity'];
					$log->currency_rate = $currency_rate;
					$log->currency_id = $currency_id;
					$log->remaining_quantity = 0;
					$log->user_id = CURRENT_USER_ID;
					$log->time = CURRENT_DATETIME;
					$log->save();
					QDB::getConn()->execute('update sales_order_item set cost_price=' . $cost_price . ' where id=' . $i['id']);
					Product_Warehouse::actualQuantityDecrease(0, $i['product_basic_id'], $warehouse_id, $i['quantity']);
					Product_Warehouse::availableQuantityDecrease(0, $i['product_basic_id'], $warehouse_id, $i['quantity']);
					Product_Warehouse::soldQuantityDecrease(0, $i['product_basic_id'], $warehouse_id, $i['quantity']);
				}
			}
		}
		return array('ack' => SUCCESS, 'message' => '');
	}
	
	static function judgeOutFBA($sales_order_id)
	{
		$sales_order = Sales_Order::find('sales_order.id=? and warehouse.is_default=?', $sales_order_id, false)
			->joinLeft('warehouse', '', 'warehouse.id=sales_order.warehouse_id')
			->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value'))
			{
				$item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
				$product = array();
				$enough = true;
				foreach ($item as $i)
				{
					$key = $i['product_basic_id'] . '_' . $sales_order['warehouse_id'];
					if ( ! array_key_exists($key, $product))
					{
						$product_warehouse = Product_Warehouse::find('product_basic_id=? and warehouse_id=?', $i['product_basic_id'], $sales_order['warehouse_id'])->asArray()->getOne();
						$inventory_log_left = Inventory_Log::find('product_basic_id=? and warehouse_id=?', $i['product_basic_id'], $sales_order['warehouse_id'])->getSum('remaining_quantity');
						$product[$key] = array('actual_quantity' => $product_warehouse['actual_quantity'], 'log_remaining' => $inventory_log_left, 'need_quantity' => 0);
					}
					$product[$key]['need_quantity'] += $i['quantity'];
					if ($product[$key]['need_quantity'] > $product[$key]['actual_quantity'] || $product[$key]['need_quantity'] > $product[$key]['log_remaining'])
					{
						$enough = false;
					}
				}
				if ($enough)
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => 'actual quantity is not enough');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order handle status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	/**
	 * 查询Winit出库情况，更新系统出库
	 * @param $winit_record_id
	 */
	static function checkOutWinit($winit_record_id)
	{
		set_time_limit(0);
		$result = Helper_BSS_API::winitAPICall(Helper_BSS_API::winitSign(array('outboundOrderNum' => $winit_record_id), 'queryOutboundOrder'), Q::ini('custom_api/Winit_api_uri'));
		$message = '';
		$sales_order = Sales_Order::find('lsp_number=?', $winit_record_id)->getOne();
		if ($result['ack'] == FAILURE)
		{
			$message = $result['message'];
		}
		else
		{
			//获得接口返回的出库单信息
			$dataList = $result['data']['list'];
			foreach ($dataList as $k => $data)
			{
				if (! empty($data['trackingNum']))
				{
					$sales_order->tracking_number = $data['trackingNum'];
					$sales_order->save();
				}
				if (! empty($data['chargeableWeight']))
				{
					$sales_order->weight = $data['chargeableWeight'] * 1000;
					$sales_order->save();
				}
				if (! empty($data['totalCost']))
				{
					$currency = Currency::find('code=?', 'USD')->asArray()->getOne();
					$sales_order->postage = $data['totalCost'];
					$sales_order->postage_currency_id = $currency['id'];
					$sales_order->postage_currency_rate = $currency['rate'];
					$sales_order->save();
				}
				if (! empty($data['status']))
				{
					if (in_array($data['status'], array('DLI', 'DLC', 'HPO')))
					{
						$result = Sales_Order::out(array($sales_order['id']));
						if ($result['ack'] == SUCCESS)
						{
							continue;
						}
						else
						{
							$message = $result['message'];
						}
					}
				}
			}
		}
		if ($message)
		{
			return array('ack' => FAILURE, 'message' => $message);
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 同步出库单到Winit（出库确认中状态）
	 * @param $ids
	 * @param $order_type
	 */
	static function expressWinit($ids, $order_type)
	{
		$itype = Helper_BSS_Normal::getIniOne('winit_order_type', 'value', $order_type, 'itype');
		$wid = Helper_BSS_Normal::getIniOne('winit_order_type', 'value', $order_type, 'wid');
		$wcode = Helper_BSS_Normal::getIniOne('winit_order_type', 'value', $order_type, 'wcode');
		if (! empty($itype) && ! empty($wcode))
		{
			$message = array();
			$sales_orders = Sales_Order::find('sales_order.id in (?) and sales_order.handle_status=?', $ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'))
				->joinLeft('warehouse', 'warehouse.code as warehouse_code', 'warehouse.id=sales_order.warehouse_id')
				->asArray()->getAll();
			foreach ($sales_orders as $so)
			{
				if ($so['warehouse_code'] == $wcode)
				{
					if ($so['synchronous_flag'] == Q::ini('custom_flag/sales_order_synchronous_flag/Winit/value'))
					{
						$message[] = $so['number'] . '：已同步过Winit！';
					}
					else
					{
						$item = Sales_Order_Item::find('sales_order_item.sales_order_id=?', $so['id'])
							->joinLeft('product_basic', 'number as product_basic_number', 'product_basic.id=sales_order_item.product_basic_id')
							->asArray()->getAll();
						$customer = Sales_Order_Customer_Info::find('sales_order_customer_info.sales_order_id=?', $so['id'])
							->joinLeft('country', 'code as country_code', 'country.en_name=sales_order_customer_info.country')
							->asArray()->getOne();
						if ($customer['country_code'])
						{
							$product_list = array();
							foreach ($item as $i)
							{
								$product =	array(
					                'eBayItemID' => $i['shop_item_id'],
					                'eBayTransactionID' => $i['shop_transaction_id'],
									'productCode' => $i['product_basic_number'],
									'productNum' => $i['quantity'],
					                );
					             $product_list[] = $product;
							}
							$data = array(
								'address1' => $customer['street1'],
								'address2' => $customer['street2'],
								'city' => $customer['city'],
								'deliveryWayID' => $order_type,
								'emailAddress' => $customer['email'],
								'insuranceTypeID' => $itype,
								'phoneNum' => $customer['phone'],
								'productList' => $product_list,
								'recipientName' => $customer['fullname'],
								'region' => $customer['state'],
								'repeatable' => (($so['send_method'] == Q::ini('custom_flag/sales_order_send_method/resend/value')) ? 'Y' : 'N'),
								'sellerOrderNo' => $so['number'],
								'state' => $customer['country_code'],
								'warehouseID' => $wid,
								'zipCode' => $customer['zip']
							);
							$result = Helper_BSS_API::winitAPICall(Helper_BSS_API::winitSign($data, 'createOutboundOrder'), Q::ini('custom_api/Winit_api_uri'));
							if ($result['ack'] == SUCCESS)
							{
								QDB::getConn()->execute('update sales_order set synchronous_flag =' . Q::ini('custom_flag/sales_order_synchronous_flag/Winit/value') . ', lsp_number=\'' . $result['data']['outboundOrderNum'] . '\' where id=' . $so['id']);
							}
							else
							{
								$message[] = $so['number'] . '：错误代码' . $result['data'] . '，' . $result['message'];
							}
						}
						else
						{
							$message[] = $so['number'] . '：国家名称在系统找不到';
						}
					}
				}
				else
				{
					$message[] = $so['number'] . '：订单所在仓库是' . $so['warehouse_code'] . '，所选派送海外仓是' . $wcode;
				}
			}
			if ($message)
			{
				return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
			}
			else
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '提交的订单方式数据有误！');
		}
	}
	
	/**
	 * 更新Winit出库单状态为作废（作废后的出库单在Winit后台不可见）
	 * @param Winit订单号 $winit_record_id
	 */
	static function updateWinitStatusToVoid($winit_record_id)
	{
		$result = Helper_BSS_API::winitAPICall(Helper_BSS_API::winitSign(array('outboundOrderNum' => $winit_record_id), 'voidOutboundOrder'), Q::ini('custom_api/Winit_api_uri'));
		if ($result['ack'] == SUCCESS)
		{
			if ($winit_record_id == $result['data']['outboundOrderNum'])
			{
				QDB::getConn()->execute('update sales_order set lsp_number=NULL, synchronous_flag=NULL where lsp_number=\'' . $winit_record_id . '\'');
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => '更新状态出错，返回id：' . $winit_record_id . '和更新id：' . $result['data']['outboundOrderNum'] . '不一样！');
			}
		}
		elseif ($result['ack'] == FAILURE)
		{
			return array('ack' => FAILURE, 'message' => $result['message']);
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '未知错误发生，联系相关技术人员！');
		}
	}
	
	/**
	 * 查询达方海外仓出库情况，更新系统出库
	 * @param $key_name 达方订单号
	 */
	static function checkOutDF($key_name)
	{
		set_time_limit(0);
		$message = array();
		$data = '&password=' . md5(Q::ini('custom_api/DF_api_upasswd')) . '&target=goods_list&op=show&key_name=' . $key_name;
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, Q::ini('custom_api/DF_api_uri') . Q::ini('custom_api/DF_api_uname'));
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);
		$response = curl_exec($ch);
		curl_close($ch);
		$result = json_decode($response, true);
		if ($result[0]['nowState'] == '已发货')
		{
			$sales_order = Sales_Order::find('lsp_number=?', $key_name)->getOne();
			if ($sales_order['id'])
			{
				$currency = Currency::find('code=?', 'CNY')->asArray()->getOne();
				$sales_order->postage = $result[0]['totalFare'];
				$sales_order->postage_currency_id = $currency['id'];
				$sales_order->postage_currency_rate = $currency['rate'];
				$sales_order->weight = $result[0]['countWeight'] * 1000;
				$sales_order->tracking_number = $result[0]['trackNo'];
				$sales_order->save();
				$result = Sales_Order::out(array($sales_order['id']));
				if ($result['ack'] == SUCCESS)
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => $result['message']);
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $key_name . '：不存在系统！');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => $key_name . '：该订单未发货，状态为：' . $result[0]['nowState']);
		}
	}

	/**
	 * 同步出库单到DF（出库确认中状态）
	 * @param $ids
	 * @param $order_type
	 */
	static function expressDF($ids, $order_type, $is_repeat=false)
	{
		$wid = Helper_BSS_Normal::getIniOne('DF_order_type', 'value', $order_type, 'wid');
		$wcode = Helper_BSS_Normal::getIniOne('DF_order_type', 'value', $order_type, 'wcode');
		if (! empty($wid) && ! empty($wcode))
		{
			$message = array();
			$sales_order = Sales_Order::find('sales_order.id in (?) and sales_order.handle_status=?', $ids, Q::ini('custom_flag/sales_order_handle_status/assigned/value'))
				->joinLeft('warehouse', 'code as warehouse_code', 'warehouse.id=sales_order.warehouse_id')
				->asArray()->getAll();
			foreach ($sales_order as $so)
			{
				if ($so['warehouse_code'] == $wcode)
				{
					$item = Sales_Order_Item::find('sales_order_item.sales_order_id=?', $so['id'])
						->joinLeft('product_basic', 'number as product_basic_number, weight', 'product_basic.id=sales_order_item.product_basic_id')
						->asArray()->getAll();
					$customer = Sales_Order_Customer_Info::find('sales_order_customer_info.sales_order_id=?', $so['id'])
						->joinLeft('country', 'code as country_code', 'country.en_name=sales_order_customer_info.country')
						->asArray()->getOne();
					if ($is_repeat)
					{
						QDB::getConn()->execute('update sales_order set synchronous_flag=NULL where id =' . $so['id']);
					}
					if ($so['synchronous_flag'] == Q::ini('custom_flag/sales_order_synchronous_flag/DF/value'))
					{
						$message[] = $so['number'] . '：已同步过达方！如需重复同步，请选择重复同步！';
					}
					else
					{
						$data = '&password=' . md5(Q::ini('custom_api/DF_api_upasswd')) . '&target=goods_list&op=add';
						$data .= '&warehouse_entity=' . $wid;
						$data .= '&servie_entity=' . $order_type;
						$data .= '&country_entity=' . $customer['country_code'];
						$data .= '&province=' . $customer['state'];
						$data .= '&city=' . $customer['city'];
						$data .= '&receiver_name=' . $customer['fullname'];
						$data .= '&receiver_address1=' . $customer['street1'] . ' ' . $customer['street2'];
						$data .= '&post_code=' . $customer['zip'];
						$data .= '&receiver_email=' . $customer['email'];
						$data .= '&receiver_phone=' . $customer['phone'];
						$data .= '&weight=' . $so['estimated_weight']/1000;
						$data .= '&insured=Y';
						$data .= '&returnDF=Y';
						$data .= '&priority=Y';
						$data .= '&reference_no=' . $so['number'];
						$data .= '&confirm_state=1';
						foreach ($item as $k => $i)
						{
							$num = $k+1;
							$data .= '&customer_label_' . $num . '=' . $i['product_basic_number'];
							$data .= '&count_' . $num . '=' . $i['quantity'];
						}
						$ch = curl_init();
						curl_setopt($ch, CURLOPT_URL, Q::ini('custom_api/DF_api_uri') . Q::ini('custom_api/DF_api_uname'));
						curl_setopt($ch, CURLOPT_POST, true);
						curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
						curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
						curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);
						$response = curl_exec($ch);
						curl_close($ch);
						if (strstr($response, 'result=OK'))
						{
							$arr = Q::normalize(str_replace(array('{[', ']}'), '', $response), ',');
							$tracking_number = $lsp_number = '';
							foreach ($arr as $a)
							{
								$tmp = Q::normalize($a, '=');
								if ($tmp[0] == 'trackNo')
								{
									$tracking_number = $tmp[1];
								}
								if ($tmp[0] == 'dfcode')
								{
									$lsp_number = $tmp[1];
								}
							}
							QDB::getConn()->execute('update sales_order set tracking_number=\''. $tracking_number . '\', lsp_number=\'' . $lsp_number . '\', synchronous_flag=\'' . Q::ini('custom_flag/sales_order_synchronous_flag/DF/value') . '\' where id=' . $so['id']);
						}
						else
						{
							$message[] = $so['number'] . '：' . $response;
						}
					}
				}
				else
				{
					$message[] = $so['number'] . '：订单所在仓库是' . $so['warehouse_code'] . '，所选派送海外仓是' . $wcode;
				}
			}
			if ($message)
			{
				return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
			}
			else
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => '提交的订单方式数据有误！');
		}
	}
	
	/**
	 * 订单出库
	 * @param $sales_order_ids
	 */
	static function out($sales_order_ids)
	{
		$message = array();
		foreach ($sales_order_ids as $id)
		{
			$judge_result = Sales_Order::judgeOut($id);
			if ($judge_result['ack'] == SUCCESS)
			{
				$sales_order = Sales_Order::find('id=?', $id)->getOne();
				$warehouse_id = $sales_order['warehouse_id'];
				$currency_id = $sales_order['currency_id'];
				$currency_rate = $sales_order['currency_rate'];
				$sales_order->handle_status = Q::ini('custom_flag/sales_order_handle_status/shipped/value');
				$sales_order->shipped_user_id = CURRENT_USER_ID;
				$sales_order->shipped_time = CURRENT_DATETIME;
				$sales_order->shipping_status = Q::ini('custom_flag/sales_order_shipping_status/shipped/value');
				$sales_order->save();
				$item = Sales_Order_Item::find('sales_order_id=?', $id)->asArray()->getAll();
				foreach ($item as $i)
				{
					$cost_amount_result = Inventory_Log::getCostAmountByFIFO($i['product_basic_id'], $warehouse_id, $i['quantity']);
					$cost_price = $cost_amount_result['cost_amount'] / $i['quantity'];
					$log = new Inventory_Log();
					$log->product_basic_id = $i['product_basic_id'];
					$log->warehouse_id = $warehouse_id;
					$log->type = Q::ini('custom_flag/inventory_log_type/sales/value');
					$log->relate_table_id = $i['id'];
					$log->init_quantity = 0;
					$log->in_quantity = 0;
					$log->out_quantity = $i['quantity'];
					$log->cost_price = $cost_price;
					$log->sales_price = $i['sales_price'];
					$log->cost_amount = $cost_amount_result['cost_amount'];
					$log->sales_amount = $i['sales_price'] * $i['quantity'];
					$log->currency_rate = $currency_rate;
					$log->currency_id = $currency_id;
					$log->remaining_quantity = 0;
					$log->user_id = CURRENT_USER_ID;
					$log->time = CURRENT_DATETIME;
					$log->save();
					QDB::getConn()->execute('update sales_order_item set cost_price=' . $cost_price . ' where id=' . $i['id']);
					Product_Warehouse::actualQuantityDecrease(0, $i['product_basic_id'], $warehouse_id, $i['quantity']);
					Product_Warehouse::soldQuantityDecrease(0, $i['product_basic_id'], $warehouse_id, $i['quantity']);
				}
			}
			else
			{
				$message[] = $judge_result['message'];
			}
		}
		if ($message)
		{
			return array('ack' => PARTIAL_FAILURE, 'message' => implode("\n", $message));
		}
		else
		{
			return array('ack' => SUCCESS, 'message' => '');
		}
	}
	
	/**
	 * 判断订单是否满足出库条件
	 * @param $sales_order_id
	 */
	static function judgeOut($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		$Winit_warehouse_ids = Warehouse::getWarehouseIdsByType('winit');
		$DF_warehouse_ids = Warehouse::getWarehouseIdsByType('dafang');
		$FBA_warehouse_ids = Warehouse::getWarehouseIdsByType('amazon');
		if ($sales_order)
		{
			$item = $product = array();
			$enough = true;
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/weighed/value'))
			{
				$item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
			}
			elseif (in_array($sales_order['warehouse_id'], $Winit_warehouse_ids) && $sales_order['synchronous_flag'] == Q::ini('custom_flag/sales_order_synchronous_flag/Winit/value') && $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/assigned/value'))
			{
				$item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
			}
			elseif (in_array($sales_order['warehouse_id'], $DF_warehouse_ids) && $sales_order['synchronous_flag'] == Q::ini('custom_flag/sales_order_synchronous_flag/DF/value') && $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/assigned/value'))
			{
				$item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
			}
			elseif (in_array($sales_order['warehouse_id'], $FBA_warehouse_ids) && $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/assigned/value'))
			{
				$item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': sales order handle status is incorrect');
			}
			foreach ($item as $i)
			{
				$key = $i['product_basic_id'] . '_' . $sales_order['warehouse_id'];
				if ( ! array_key_exists($key, $product))
				{
					$product_warehouse = Product_Warehouse::find('product_basic_id=? and warehouse_id=?', $i['product_basic_id'], $sales_order['warehouse_id'])->asArray()->getOne();
					$inventory_log_left = Inventory_Log::find('product_basic_id=? and warehouse_id=?', $i['product_basic_id'], $sales_order['warehouse_id'])->getSum('remaining_quantity');
					$product[$key] = array('actual_quantity' => $product_warehouse['actual_quantity'], 'log_remaining' => $inventory_log_left, 'need_quantity' => 0);
				}
				$product[$key]['need_quantity'] += $i['quantity'];
				if ($product[$key]['need_quantity'] > $product[$key]['actual_quantity'] || $product[$key]['need_quantity'] > $product[$key]['log_remaining'])
				{
					$enough = false;
				}
			}
			if ($enough)
			{
				return array('ack' => SUCCESS, 'message' => '');
			}
			else
			{
				return array('ack' => FAILURE, 'message' => $sales_order['number'] . ': actual quantity is not enough');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	static function judgeRefund($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->asArray()->getOne();
		if ($sales_order)
		{
			if ($sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value')
				|| $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value')
				|| $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/shipped/value')
				|| $sales_order['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/return/value'))
			{
				if ($sales_order['sales_time'] >= date('Y-m-d', strtotime(CURRENT_DATETIME . ' -6 months')))
				{
					return array('ack' => SUCCESS, 'message' => '');
				}
				else
				{
					return array('ack' => FAILURE, 'message' => 'sales time more than six months');
				}
			}
			else
			{
				return array('ack' => FAILURE, 'message' => 'sales order handle status is incorrect');
			}
		}
		else
		{
			return array('ack' => FAILURE, 'message' => 'sales order is not exists');
		}
	}
	
	static function checkEnoughUsable(&$sales_order)
	{
		$product_arr = array();
		foreach ($sales_order as &$so)
		{
			$item = Sales_Order_Item::find('sales_order_id=?', $so['id'])->asArray()->getAll();
			$so['can_check'] = false;
			if ($so['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/new/value') || $so['handle_status'] == Q::ini('custom_flag/sales_order_handle_status/sales_hold/value'))
			{
				$so['can_check'] = true;
				foreach ($item as $i)
				{
					$key = $i['product_basic_id'] . '_' . $so['warehouse_id'];
					if ( ! array_key_exists($key, $product_arr))
					{
						$product_warehouse = Product_warehouse::find('product_basic_id = ? and warehouse_id=?', $i['product_basic_id'], $so['warehouse_id'])->asArray()->getOne();
						$product_arr[$key]['available_quantity'] = $product_warehouse['available_quantity'];
					}
					$product_arr[$key]['available_quantity'] -= $i['quantity'];
					if ($product_arr[$key]['available_quantity'] < 0)
					{
						$so['can_check'] = false;
					}
				}
			}
		}
		unset($so);
	}
	
	static function checkWarning(&$sales_order)
	{
		$sales_order_trash_status_normal = Q::ini('custom_flag/sales_order_trash_status/normal/value');
		foreach ($sales_order as &$so)
		{
			$so['warning'] = false;
			
			if (!$so['zip'] || !$so['state'] || strlen($so['fullname'])>80 || !$so['city'] || $so['country'] == 'USA' || !$so['country'] || strlen($so['phone'])>20 || !count($so['item']) || strlen($so['city'])>50 || strlen($so['state'])>80 || strlen($so['zip'])>10 || !$so['country_cn'])
			{
				$so['warning'] = true;
			}
			elseif (strpos($so['fullname'], '?') !== false || strpos($so['city'], '?') !== false || strpos($so['state'], '?') !== false || strpos($so['street1'], '?') !== false || strpos($so['street2'], '?') !== false)
			{
				$so['warning'] = true;
			}
			elseif (stripos($so['street1'], 'Packstation') !== false || stripos($so['street1'], 'Filiale') !== false || stripos($so['street2'], 'Packstation') !== false)
			{
				$so['warning'] = true;
			}
			else
			{
				foreach ($so['item'] as $soi)
				{
					if ($soi['quantity'] <= 0)
					{
						$so['warning'] = true;
					}
				}
			}
		}
		unset($so);
	}
	
	static function calculateWeight(&$sales_order)
	{
		foreach ($sales_order as &$so)
		{
			$so['calculate_weight'] = $material_weight = 0;
			if (isset($so['item'][0]))
			{
				$material_weight = QDB::getConn()->execute('select product_material.weight from product_warehouse left join product_material on product_warehouse.product_material_id=product_material.id where product_warehouse.product_basic_id=' . $so['item'][0]['product_basic_id'])->fetchOne();
				foreach ($so['item'] as $i)
				{
					$product_weight = QDB::getConn()->execute('select weight from product_basic where id=' . $i['product_basic_id'])->fetchOne();
					$so['calculate_weight'] += $product_weight*$i['quantity'];
				}
			}
			$so['calculate_weight'] += $material_weight;
		}
		unset($so);
	}
	
	/**
	 * 判断是否高亮该订单买家ID或name
	 * @param $sales_order
	 */
	static function checkBuyer(&$sales_order)
	{
		$res = array_column($sales_order, 'shop_buyer_id');
		$_res = array_column($sales_order, 'fullname');
		foreach ($sales_order as &$so)
		{
			$so['buyerrepeat'] = false;
			$so['checkname'] = false;
			$countid = array_count_values($res);
			if ($countid[$so['shop_buyer_id']] > 1)
			{
				$so['buyerrepeat'] = true;
				$countname = array_count_values($_res);
				if ($countname[$so['fullname']] == 1)
				{
					$so['checkname'] = true;
				}
			}
		}
		unset($so);
	}
	
	/**
	 * 导入销售订单自动检测选择对应的邮寄方式
	 * @param $order_id
	 */
	static function selectShippingMethod($order_id, $param)
	{
		$order = Sales_Order::find('sales_order.id=?', $order_id)
			->joinLeft('shop', 'platform as shop_platform, name as shop_name', 'shop.id=sales_order.shop_id')
			->asArray()->getOne();
		$customer_info = Sales_Order_Customer_Info::find('sales_order_customer_info.sales_order_id=?', $order_id)
			->joinLeft('country', 'code as country_code', 'country.en_name=sales_order_customer_info.country')
			->asArray()->getOne();
		$item = Sales_Order_Item::find('sales_order_id=?', $order_id)
			->joinLeft('product_basic', 'product_basic.number as product_basic_number', 'product_basic.id=sales_order_item.product_basic_id')
			->asArray()->getAll();
		$platform = $order['shop_platform'];
		$shop_name = explode('-', $order['shop_name']);
		$shipping_method = $order['shipping_method'];
		$country_code = $customer_info['country_code'];
		$channel = isset($param['channel']) ? $param['channel'] : '';
		$is_qt_de = $is_sgp = $is_sku = false;
		if ($item)
		{
			foreach ($item as $i)
			{
				if (in_array($i['product_basic_number'], array('N000406', 'N000405', 'N000202', 'N000201', 'N000200', 'N000199', 'N000198', 'N000197', 'N000153', 'N000152', 'N000342', 'N000321', 'N000320', 'N000228', 'N000227')))
				{
					$is_sku = true;
				}
				elseif (in_array($i['product_basic_number'], array('N000588','N000587','N000586','N000585','N000584','N000583','N000582','N000581','N000580','N000579','N000578','N000577','N000576','N000575','N000574','N000573','N000572','N000571','N000570','N000569','N000568','N000567','N000566','N000565','N000564','N000563')))
				{
					$is_sgp = true;
				}
				elseif (in_array($i['product_basic_number'], array('W000053','W000054','WG000061','W000506','W000969','W000970','W001122','W001194','N000198','N000199','N000200','N000201','N000202','N000227','N000228','N000405')));
				{
					$is_qt_de = true;
				}
			}
		}
		if ($is_sgp)
		{
			$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_SG_Mail');
		}
		elseif (isset($shop_name[1]) && in_array($shop_name[1], array('US', 'MX', 'CA')))
		{
			if ($channel == 'AFN')
			{
				$shipping_method = Shipping_Method::getShippingMethodByCode('FBA');
			}
			elseif ($channel == 'MFN')
			{
				if (in_array($country_code, array('US')))
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BY_IEUB');
				}
				elseif (in_array($country_code, array('CA')))
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BUB');
				}
				else
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_SG_Mail');
				}
			}
		}
		elseif (isset($shop_name[1]) && in_array($shop_name[1], array('UK', 'DE', 'FR', 'ES', 'IT')))
		{
			if ($channel == 'AFN')
			{
				$shipping_method = Shipping_Method::getShippingMethodByCode('FBA');
			}
			elseif ($channel == 'MFN')
			{
				if ($is_sku)
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_R_SG_Package');
				}
				elseif (in_array($country_code, array('CA')))
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BUB');
				}
				elseif (in_array($country_code, array('GB')))
				{
					if (count($item) >= 2)
					{
						$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_QT_GB_P');
// 						$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BY_GB_Line_Packet2');
					}
					else		
					{
						$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_QT_GB');
// 						$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BY_GB_Line_Letter2');
					}
				}
				elseif (in_array($country_code, array('DE','IT')))
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_QT_EU_RM');
					if ($is_qt_de)
					{
						$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_QT_DE');
					}
// 					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BY_EU_Line_RM');
				}
				elseif (in_array($country_code, array('AT','ES','FR','NL')))
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_QT_EU');
// 					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BY_EU_Line_NL');
				}
				else
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_SG_Mail');
				}
			}
		}
		elseif ($platform == 'ebay')
		{
			if (in_array($country_code, array('US')))
			{
				$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_EUB');
			}
			elseif (in_array($country_code, array('IT','CZ','DK','BE','PT','IE','GB','AU','IL','DE','NL','SE','NO','CA','FR','ES','RU','BR','AR','JP')))
			{
				$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_BUB');
				if ($is_qt_de)
				{
					$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_QT_DE');
				}
			}
			else
			{
				$shipping_method = Shipping_Method::getShippingMethodByCode('GZ_N_SG_Mail');
			}
		}
		Sales_Order::updateShippingMethod($order['id'], $shipping_method);
	}
	
	static function updateShippingMethod($sales_order_id, $shipping_method_id)
	{
		$sales_order = Sales_order::find('id=?', $sales_order_id)->getOne();
		if ($sales_order['id'])
		{
			$old_warehouse_id = $sales_order['warehouse_id'];
			$shipping_method = Shipping_Method::find('id=?', $shipping_method_id)->asArray()->getOne();
			if ($shipping_method && ($old_warehouse_id != $shipping_method['warehouse_id']))			
			{
				$sales_order->warehouse_id = $shipping_method['warehouse_id'];
				$sales_order->save();
				$item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)
					->joinLeft('product_basic', 'product_basic.number as product_basic_number', 'product_basic.id=sales_order_item.product_basic_id')
					->asArray()->getAll();
				Sales_Order_Item::update($item, $sales_order_id, 'check_db', $old_warehouse_id);
			}
			$sales_order->shipping_method = $shipping_method_id;
			$sales_order->save();
		}
	}

	/**
	 * 更新订单系统估重的字段
	 * @param $sales_order_id 销售订单id
	 */
	static function updateEstimatedWeight($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->getOne();
		if ($sales_order['id'])
		{
			$sales_order_item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
			$estimated_weight = $material_weight = 0;
			if (isset($sales_order_item[0]['product_basic_id']))
			{
				$material_weight = QDB::getConn()->execute('select product_material.weight from product_warehouse left join product_material on product_warehouse.product_material_id=product_material.id where product_warehouse.product_basic_id=' . $sales_order_item[0]['product_basic_id'])->fetchOne();
			}
			foreach ($sales_order_item as $soi)
			{
				$product_weight = QDB::getConn()->execute('select weight from product_basic where id=' . $soi['product_basic_id'])->fetchOne();
				$estimated_weight += $product_weight * $soi['quantity'];
			}
			$estimated_weight += $material_weight;
			$sales_order->estimated_weight = $estimated_weight;
			$sales_order->save();
		}
	}
	
	/**
	 * 更新订单架位的字段
	 * @param $sales_order_id 销售订单id
	 */
	static function updateSortShelfPosition($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->getOne();
		if ($sales_order['id'])
		{
			$sales_order_item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)
				->joinLeft('product_warehouse', 'shelf_position', 'product_warehouse.product_basic_id=sales_order_item.product_basic_id and product_warehouse.warehouse_id=' . $sales_order['warehouse_id'])
				->order('product_warehouse.shelf_position asc')->asArray()->getAll();
			if (count($sales_order_item))
			{
				$sales_order['sort_shelf_position'] = $sales_order_item[0]['shelf_position'];
				$sales_order->save();
			}
		}
	}
	
	/**
	 * 更新销售订单信息
	 * @param $sales_order_id 销售订单id
	 */
	static function updateOrder($sales_order_id)
	{
		$sales_order = Sales_Order::find('id=?', $sales_order_id)->getOne();
		if ($sales_order['id'])
		{
			$product_quantity = 0;
			$product_arr = array();
			$amount = $sales_order['shipping_fee'] - $sales_order['discount'];
			$sales_order_item = Sales_Order_Item::find('sales_order_id=?', $sales_order_id)->asArray()->getAll();
			foreach ($sales_order_item as $soi)
			{
				$soi['attr'] = Sales_Order_Item_Attribute::find('sales_order_item_id=?', $soi['id'])->asArray()->getAll();
				$amount += $soi['quantity'] * $soi['sales_price'];
				foreach ($soi['attr'] as $oia)
				{
					if ($oia['prefix'] == '+')
					{
						$amount += $oia['price'] * $soi['quantity'];
					}
					elseif ($oia['prefix'] == '-')
					{
						$amount -= $oia['price'] * $soi['quantity'];
					}
				}
				$product_quantity += $soi['quantity'];
				if (in_array($soi['product_basic_id'], $product_arr))
				{
					continue;
				}
				$product_arr[] = $soi['product_basic_id'];
			}
			$sales_order->amount = $amount;
			$sales_order->product_quantity = $product_quantity;
			$sales_order->product_sort_quantity = count($product_arr);
			$sales_order->save();
		}
	}
	
	/**
	 * 检测是否存在捆绑SKU分解为系统SKU
	 * @param 需要分解item $item
	 */
	static function productBingResolved($item)
	{
		$new_item = array();
		if ($item)
		{
			foreach ($item as $i)
			{
				$check_in_bind = Product_Bind::find('number=?', $i['product_basic_number'])->asArray()->getOne();
				if ($check_in_bind['id'])
				{
					$product_bind_item = Product_Bind_Item::find('product_bind_id=?', $check_in_bind['id'])
						->joinLeft('product_basic', 'number', 'product_basic.id=product_bind_item.product_basic_id')
						->asArray()->getAll();
					$total_quantity = QDB::getConn()->execute('select sum(quantity) from product_bind_item where product_bind_id=' . $check_in_bind['id'])->fetchOne();
					foreach ($product_bind_item as $pbi)
					{
						$new_item[] = array(
							'product_basic_number' => $pbi['number'],
							'quantity' => $i['quantity'] * $pbi['quantity'],
							'sales_price' => $i['sales_price'] / $total_quantity,
							'shop_item_id' => $i['shop_item_id'],
							'shop_transaction_id' => isset($i['shop_transaction_id']) ? $i['shop_transaction_id'] : ''
						);
					}
				}
				else
				{
					$new_item[] = $i;
				}
			}
		}
		return $new_item;
	}
	
	/**
	 * 按条件搜索销售单
	 * @param $condition 条件
	 * @param $cp 当前页
	 * @param $ps 每页大小
	 */
	static function search($condition, $cp, $ps, $sort_order='sales_order.sales_time asc')
	{
		set_time_limit(0);
		$columns = array(
			'sales_order_customer_info.*',
			'sales_order.*',
			'shop.name as shop_name',
			'a.name as make_user_name, b.name as sales_user_name, c1.name as print_user_name, c2.name as print_address_user_name, d.name as weigh_user_name, e.name as checkout_user_name, f.name as shipped_user_name, g.name as pick_user_name, h.name as pack_user_name',
			'warehouse.name as warehouse_name',
			'ca.code as currency_code, ca.symbol as currency_symbol, cb.symbol as postage_currency_symbol, cb.code as postage_currency_code',
			'shipping_method.name as shipping_method_name'
		);
		$where = Sales_Order::buildSearchWhere($condition);
		if ($cp == 0 && $ps == 0)
		{
			$select = Sales_Order::find($where)
				->joinLeft('shop', '', 'shop.id=sales_order.shop_id')
				->joinLeft('user as a', '', 'a.id=sales_order.make_user_id')
				->joinLeft('user as b', '', 'b.id=sales_order.sales_user_id')
				->joinLeft('user as c1', '', 'c1.id=sales_order.print_user_id')
				->joinLeft('user as c2', '', 'c2.id=sales_order.print_address_user_id')
				->joinLeft('user as d', '', 'd.id=sales_order.weigh_user_id')
				->joinLeft('user as e', '', 'e.id=sales_order.checkout_user_id')
				->joinLeft('user as f', '', 'f.id=sales_order.shipped_user_id')
				->joinLeft('user as g', '', 'g.id=sales_order.pick_user_id')
				->joinLeft('user as h', '', 'h.id=sales_order.pack_user_id')
				->joinLeft('warehouse', '', 'warehouse.id=sales_order.warehouse_id')
				->joinLeft('sales_order_customer_info', '', 'sales_order_customer_info.sales_order_id=sales_order.id')
				->joinLeft('currency as ca', '', 'ca.id=sales_order.currency_id')
				->joinLeft('currency as cb', '', 'cb.id=sales_order.postage_currency_id')
				->joinLeft('shipping_method', '', 'shipping_method.id=sales_order.shipping_method');
			if (isset($condition['sales_status']) && isset($condition['order_status']) || isset($condition['shop_item_id']))
			{
				$select->joinLeft('sales_order_item', '', 'sales_order_item.sales_order_id=sales_order.id')
					   ->joinLeft('product_warehouse', '', 'sales_order_item.product_basic_id=product_warehouse.product_basic_id and product_warehouse.warehouse_id=sales_order.warehouse_id')
					   ->group('sales_order.id');
			}
			$select->order($sort_order)->setColumns($columns);
			$pagination = array();
		}
		else
		{
			$select = Sales_Order::find($where)
				->joinLeft('shop', '', 'shop.id=sales_order.shop_id')
				->joinLeft('user as a', '', 'a.id=sales_order.make_user_id')
				->joinLeft('user as b', '', 'b.id=sales_order.sales_user_id')
				->joinLeft('user as c1', '', 'c1.id=sales_order.print_user_id')
				->joinLeft('user as c2', '', 'c2.id=sales_order.print_address_user_id')
				->joinLeft('user as d', '', 'd.id=sales_order.weigh_user_id')
				->joinLeft('user as e', '', 'e.id=sales_order.checkout_user_id') 
				->joinLeft('user as f', '', 'f.id=sales_order.shipped_user_id')
				->joinLeft('user as g', '', 'g.id=sales_order.pick_user_id')
				->joinLeft('user as h', '', 'h.id=sales_order.pack_user_id')
				->joinLeft('warehouse', '', 'warehouse.id=sales_order.warehouse_id')
				->joinLeft('sales_order_customer_info', '', 'sales_order_customer_info.sales_order_id=sales_order.id')
				->joinLeft('currency as ca', '', 'ca.id=sales_order.currency_id')
				->joinLeft('currency as cb', '', 'cb.id=sales_order.postage_currency_id')
				->joinLeft('shipping_method', '', 'shipping_method.id=sales_order.shipping_method');
			if (isset($condition['sales_status']) && isset($condition['order_status']) || isset($condition['shop_item_id']))
			{
				$select->joinLeft('sales_order_item', '', 'sales_order_item.sales_order_id=sales_order.id')
					   ->joinLeft('product_warehouse', '', 'sales_order_item.product_basic_id=product_warehouse.product_basic_id and product_warehouse.warehouse_id=sales_order.warehouse_id')
					   ->group('sales_order.id');
			}
			$select->order($sort_order)->setColumns($columns)->limitPage($cp, $ps);
			$pagination = $select->getPagination();
		}
		$sales_order = $select->asArray()->getAll();
		return array(
				'ack' => SUCCESS,
				'message' => '',
				'data' => $sales_order,
				'pagination' => $pagination
		);
	}
	
	/**
	 * 组装搜索条件
	 * @param $condition 条件数组
	 */
	static function buildSearchWhere($condition)
	{
		$where = '1';
		if (! empty($condition['is_sm']))
		{
			$where .= ' and (sales_order.shipping_method=\'\' or sales_order.shipping_method is NULL)';
		}
		if (isset($condition['shop_user_mapping']))
		{
			$where .= ' and sales_order.shop_id in (\'' . implode('\',\'', $condition['shop_user_mapping']) . '\')';
		}
		if ( ! empty($condition['lately_six_months']))
		{
			$where .= ' and sales_order.make_time>=\'2012-05-01\'';
		}
		if ( ! empty($condition['begin_make_time']))
		{
			$where .= ' and sales_order.make_time>=\'' . $condition['begin_make_time'] . '\'';
		}
		if ( ! empty($condition['end_make_time']))
		{
			$where .= ' and sales_order.make_time<=\'' . $condition['end_make_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['begin_sales_time']))
		{
			$where .= ' and sales_order.sales_time>=\'' . $condition['begin_sales_time'] . '\'';
		}
		if ( ! empty($condition['end_sales_time']))
		{
			$where .= ' and sales_order.sales_time<=\'' . $condition['end_sales_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['begin_checkout_time']))
		{
			$where .= ' and sales_order.checkout_time>=\'' . $condition['begin_checkout_time'] . '\'';
		}
		if ( ! empty($condition['end_checkout_time']))
		{
			$where .= ' and sales_order.checkout_time<=\'' . $condition['end_checkout_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['begin_shipped_time']))
		{
			$where .= ' and sales_order.shipped_time>=\'' . $condition['begin_shipped_time'] . '\'';
		}
		if ( ! empty($condition['end_shipped_time']))
		{
			$where .= ' and sales_order.shipped_time<=\'' . $condition['end_shipped_time'] . ' 23:59:59\'';
		}
		if ( ! empty($condition['country_en_cn']))
		{
			$where .= ' and ( sales_order_customer_info.country like \'%' . $condition['country_en_cn'] . '%\' or sales_order_customer_info.country_cn like \'%' . $condition['country_en_cn'] . '%\' ) ';
		}
		if ( ! empty($condition['state']))
		{
			$where .= ' and sales_order_customer_info.state=\'' . $condition['state'] . '\'';
		}
		if ( ! empty($condition['shop_id']))
		{
			if (is_array($condition['shop_id']))
			{
				$shop = implode(',', $condition['shop_id']);
				$where .= " and sales_order.shop_id in ({$shop})";
			}
			else
			{
				$where .= ' and sales_order.shop_id=\'' . $condition['shop_id'] . '\'';
			}
		}
		if (isset($condition['warehouse_id']) && (! empty($condition['warehouse_id']) || $condition['warehouse_id'] == array()))
		{
			$warehouse_filter = '0';
			if (is_array($condition['warehouse_id']))
			{
				foreach ($condition['warehouse_id'] as $w)
				{
					$warehouse_filter .= ' or sales_order.warehouse_id=\'' . $w . '\'';
				}
			}
			else
			{
				$warehouse_filter .= ' or sales_order.warehouse_id=\'' . $condition['warehouse_id'] . '\'';
			}
			$where .= " and ($warehouse_filter)";
		}
		if ( ! empty($condition['weight_operator']))
		{
			if (isset($condition['weight']) && $condition['weight'])
			{
				$where .= " and sales_order.estimated_weight" . $condition['weight_operator'] . $condition['weight'];
			}
		}
		if (! empty($condition['product_number']))
		{
			$sales_order = QDB::getConn()->execute('select distinct(sales_order.id) from sales_order left join sales_order_item on sales_order_item.sales_order_id=sales_order.id left join product_basic on product_basic.id=sales_order_item.product_basic_id where product_basic.number=\''.$condition['product_number'].'\'')->fetchAll();
			$product_number_filter = '';
			foreach ($sales_order as $so)
			{
				$product_number_filter .= $so['id'] . ',';
			}
			if ($product_number_filter)
			{
				$where .= " and sales_order.id in (" . substr($product_number_filter, 0, -1) . ")";
			}
			else
			{
				$where .= " and sales_order.id=''";
			}
		}
		if ( ! empty($condition['number']))
		{
			$where .= ' and sales_order.number =\'' . $condition['number'] . '\'';
		}
		if ( ! empty($condition['numbers']))
		{
			$numbers = explode(',', $condition['numbers']);
			foreach ($numbers as $k => $n)
			{
				$numbers[$k] = '\'' . $n . '\'';
			}
			$where .= " and sales_order.number in (" . implode(',', $numbers) . ")";
		}
		if ( ! empty($condition['shop_order_number']))
		{
			$where .= ' and sales_order.shop_order_number=\'' . $condition['shop_order_number'] . '\'';
		}
		if ( ! empty($condition['shop_buyer_id']))
		{
			$where .= ' and sales_order_customer_info.shop_buyer_id like \'%' . $condition['shop_buyer_id'] . '%\'';
		}
		if ( ! empty($condition['fullname']))
		{
			$where .= ' and sales_order_customer_info.fullname like \'%' . $condition['fullname'] . '%\'';
		}
		if ( ! empty($condition['email']))
		{
			$where .= ' and sales_order_customer_info.email like \'%' . $condition['email'] . '%\'';
		}
		if ( ! empty($condition['country']))
		{
			$where .= " and sales_order_customer_info.country='" . $condition['country'] . "'";
		}
		if ( ! empty($condition['shop_buyer_id']))
		{
			$where .= ' and sales_order_customer_info.shop_buyer_id=\'' . $condition['shop_buyer_id'] . '\'';
		}
		if ( ! empty($condition['send_method']))
		{
			$where .= ' and sales_order.send_method=\'' . $condition['send_method'] . '\'';
		}
		if ( ! empty($condition['order_amount_more_than']))
		{
			$where .= ' and sales_order.amount>=' . $condition['order_amount_more_than'];
		}
		if ( ! empty($condition['tracking_number']))
		{
			$where .= ' and sales_order.tracking_number=\'' . $condition['tracking_number'] . '\'';
		}
		if ( ! empty($condition['shipping_status']))
		{
			$where .= ' and sales_order.shipping_status=\'' . $condition['shipping_status'] . '\'';
		}
		if ( ! empty($condition['lsp_number']))
		{
			$where .= ' and sales_order.lsp_number=\'' . $condition['lsp_number'] . '\'';
		}
		if (isset($condition['order_status']))
		{
			$order_status_filter = '0';
			foreach (Q::ini('custom_flag/sales_order_handle_status') as $os)
			{
				if (isset($condition['order_status'][$os['value']]) && $condition['order_status'][$os['value']] == $os['value'])
				{
					$order_status_filter .= ' or sales_order.handle_status=\'' . $os['value'] . '\'';
				}
			}
			$where .= " and ($order_status_filter)";
		}
		if (isset($condition['sales_status']) && isset($condition['order_status']))
		{
			$sales_status_filter = '0';
			foreach (Q::ini('custom_flag/product_sales_status') as $ss)
			{
				if (isset($condition['sales_status'][$ss['value']]) && $condition['sales_status'][$ss['value']] == $ss['value'])
				{
					$sales_status_filter .= ' or product_warehouse.sales_status=' . $ss['value'];
				}
			}
			$where .= ' and (' . $sales_status_filter . ')';
		}
		if (isset($condition['order_operate_status']))
		{
			$where .= ' and (sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/assigned/value') . '\' or sales_order.handle_status=\''. Q::ini('custom_flag/sales_order_handle_status/printed/value') . '\' or sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/printed_address/value') . '\' or sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/weighed/value') . '\' or sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/warehouse_hold/value') . '\')';
		}
		if (isset($condition['ukoverseas_order_operate_status']))
		{
			$where .= ' and (sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/assigned/value') . '\' or sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/printed_address/value') . '\' or sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/weighed/value') . '\' or sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/warehouse_hold/value') . '\' or sales_order.handle_status=\''. Q::ini('custom_flag/sales_order_handle_status/shipped/value') . '\')';
		}
		if (isset($condition['overseas_order_operate_status']))
		{
			$where .= ' and (sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/assigned/value') . '\' or sales_order.handle_status=\'' . Q::ini('custom_flag/sales_order_handle_status/warehouse_hold/value') . '\')';
		}
		if (isset($condition['trash_status']))
		{
			if ($condition['trash_status'] == Q::ini('custom_flag/sales_order_trash_status/normal/value'))
			{
				$where .=' and (sales_order.trash_status=\'' . $condition['trash_status'] . '\' or sales_order.trash_status is null)';
			}
			else
			{
				$where .=' and sales_order.trash_status=\'' . $condition['trash_status'] . '\'';
			}
		}
		if (isset($condition['shipping_method']))
		{
			$shipping_method_filter = '0';
			$shipping_method = Shipping_Method::find()->asArray()->getAll();
			foreach ($shipping_method as $sm)
			{
				if (isset($condition['shipping_method'][$sm['id']]) && $condition['shipping_method'][$sm['id']] == $sm['id'])
				{
					$shipping_method_filter .= " or sales_order.shipping_method='{$sm['id']}'";
				}
			}
			$where .= " and ($shipping_method_filter)";
		}
		if (isset($condition['is_tracking_number']))
		{
			$is_track_number_filter = '0';
			if (isset($condition['is_tracking_number'][1]))
			{
				$is_track_number_filter .= " or sales_order.tracking_number ='' or sales_order.tracking_number is null";
			}
			if (isset($condition['is_tracking_number'][2]))
			{
				$is_track_number_filter .= " or (sales_order.tracking_number !='' and sales_order.tracking_number is not null)";
			}
			$where .= " and ($is_track_number_filter)";
		}
		if (isset($condition['is_express']))
		{
			$is_express_fitler = '0';
			if (isset($condition['is_express'][1]))
			{
				$is_express_fitler .= ' or sales_order.synchronous_flag is null or sales_order.synchronous_flag = 0';
			}
			if (isset($condition['is_express'][2]))
			{
				$is_express_fitler .= ' or (sales_order.synchronous_flag is not null and sales_order.synchronous_flag <> 0)';
			}
			$where .= " and ($is_express_fitler)";
		}
		if (isset($condition['is_tracking']))
		{
			$where .= ' and ((sales_order.tracking_number is not null and sales_order.tracking_number <> \'\') or sales_order.handle_status= ' . Q::ini('custom_flag/sales_order_handle_status/shipped/value') . ')';
		}
		if (isset($condition['product_quantity_area']))
		{
			$product_quantity_area_filter = '0';
			if (isset($condition['product_quantity_area']['single']))
			{
				$product_quantity_area_filter .= ' or sales_order.product_quantity=1';
			}
			if (isset($condition['product_quantity_area']['multi']))
			{
				$product_quantity_area_filter .= ' or sales_order.product_quantity>1';
			}
			$where .= " and ($product_quantity_area_filter)";
		}
		if (isset($condition['address_print_flag']))
		{
			$address_print_flag_filter = '0';
			foreach (Q::ini('custom_flag/sales_order_address_print_flag') as $apf)
			{
				if (isset($condition['address_print_flag'][$apf['value']]) && $condition['address_print_flag'][$apf['value']] == $apf['value'])
				{
					$address_print_flag_filter .= ' or sales_order.address_print_flag=' . $apf['value'];
				}
			}
			$where .= " and ($address_print_flag_filter)";
		}
		if ( ! empty($condition['sort_shelf_position']))
		{
			$where .= " and sales_order.sort_shelf_position REGEXP '" . $condition['sort_shelf_position'] . "'";
		}
		if (isset($condition['mark_shipped_flag']))
		{
			$mark_shipped_flag_filter = '0';
			foreach (Q::ini('custom_flag/sales_order_mark_shipped_flag') as $msf)
			{
				if (isset($condition['mark_shipped_flag'][$msf['value']]) && $condition['mark_shipped_flag'][$msf['value']] == $msf['value'])
				{
					$mark_shipped_flag_filter .= ' or sales_order.mark_shipped_flag=' . $msf['value'];
				}
			}
			$where .= " and ($mark_shipped_flag_filter)";
		}
		if (isset($condition['wanted_edit']))
		{
			$is_wanted_edit_fitler = '0';
			foreach (Q::ini('custom_flag/sales_order_tips_flag') as $sotf)
			{
				if (isset($condition['wanted_edit'][$sotf['value']]) && $condition['wanted_edit'][$sotf['value']] == $sotf['value'])
				{
					$is_wanted_edit_fitler .= ' or sales_order.tips_flag=' . $sotf['value'];
				}
			}
			$where .= " and ($is_wanted_edit_fitler)";
		}
		if (isset($condition['recently_100_days']))
		{
			$where .= ' and sales_order.sales_time>=\'' . date('Y-m-d', strtotime(date('Y-m-d',CURRENT_TIMESTAMP).' -150 days')) . '\'';
		}
		if ( ! empty($condition['begin_loan_time']))
		{
			$where .= ' and sales_order.loan_time>=\'' . $condition['begin_loan_time'] . '\'';
		}
		if ( ! empty($condition['end_loan_time']))
		{
			$where .= ' and sales_order.loan_time<=\'' . $condition['end_loan_time'] . ' 23:59:59\'';
		}
		if (isset($condition['loan_status']))
		{
			$is_loan_status = '0';
			if (isset($condition['loan_status'][0]))
			{
				$is_loan_status .= ' or sales_order.loan_amount is null';
			}
			if (isset($condition['loan_status'][1]))
			{
				$is_loan_status .= ' or sales_order.loan_amount is not null';
			}
			$where .= " and ($is_loan_status)";
		}
		if (isset($condition['print_user_id']))
		{
			$where .= ' and sales_order.print_user_id=' . $condition['print_user_id'];
		}
		if (isset($condition['begin_print_time']))
		{
			$where .= ' and sales_order.print_time>=\'' . $condition['begin_print_time'] . '\'';
		}
		if (isset($condition['end_print_time']))
		{
			$where .= ' and sales_order.print_time<=\'' . $condition['end_print_time'] . '\''; 
		}
		if ( ! empty($condition['shop_item_id']))
		{
			$where .= ' and sales_order_item.shop_item_id=\'' . $condition['shop_item_id'] . '\'';
		}
		if (isset($condition['shop_transaction_id']))
		{
			$where .= ' and sales_order_item.shop_transaction_id=\'' . $condition['shop_transaction_id'] . '\'';
		}
		if ( ! empty($condition['mark_order_flag']))
		{
			$s = implode(',',$condition['mark_order_flag']);
			$where .= " and sales_order.mark_order_flag in ({$s})";
		}
		return $where;
	}
}
